mirror of https://github.com/axmolengine/axmol.git
issue #1517: Updated js library for android.
This commit is contained in:
parent
08bb6718cd
commit
476a184a09
|
@ -1,42 +1,9 @@
|
||||||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||||
* vim: set ts=4 sw=4 et tw=99 ft=cpp:
|
* vim: set ts=4 sw=4 et tw=99 ft=cpp:
|
||||||
*
|
*
|
||||||
* ***** BEGIN LICENSE BLOCK *****
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
* 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/. */
|
||||||
* 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__
|
#ifndef BitArray_h__
|
||||||
#define BitArray_h__
|
#define BitArray_h__
|
||||||
|
|
|
@ -1,48 +1,16 @@
|
||||||
/* -*- 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 -*-
|
||||||
* vim: set ts=8 sw=4 et tw=78:
|
* vim: set ts=8 sw=4 et tw=78:
|
||||||
*
|
*
|
||||||
* ***** BEGIN LICENSE BLOCK *****
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
* 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/. */
|
||||||
* 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___
|
#ifndef jsgc_barrier_h___
|
||||||
#define jsgc_barrier_h___
|
#define jsgc_barrier_h___
|
||||||
|
|
||||||
#include "jsapi.h"
|
#include "jsapi.h"
|
||||||
#include "jscell.h"
|
|
||||||
|
|
||||||
|
#include "gc/Heap.h"
|
||||||
#include "js/HashTable.h"
|
#include "js/HashTable.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -140,12 +108,10 @@
|
||||||
* and jsid, respectively.
|
* and jsid, respectively.
|
||||||
*
|
*
|
||||||
* One additional note: not all object writes need to be barriered. Writes to
|
* 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
|
* newly allocated objects do not need a pre-barrier. In these cases, we use
|
||||||
* allowed to run in between the allocation and the write. In these cases, we
|
* the "obj->field.init(value)" method instead of "obj->field = value". We use
|
||||||
* use the "obj->field.init(value)" method instead of "obj->field = value".
|
* the init naming idiom in many places to signify that a field is being
|
||||||
* We use the init naming idiom in many places to signify that a field is being
|
* assigned for the first time.
|
||||||
* assigned for the first time, and that no GCs have taken place between the
|
|
||||||
* object allocation and the assignment.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct JSXML;
|
struct JSXML;
|
||||||
|
@ -153,31 +119,39 @@ struct JSXML;
|
||||||
namespace js {
|
namespace js {
|
||||||
|
|
||||||
template<class T, typename Unioned = uintptr_t>
|
template<class T, typename Unioned = uintptr_t>
|
||||||
class HeapPtr
|
class EncapsulatedPtr
|
||||||
{
|
{
|
||||||
|
protected:
|
||||||
union {
|
union {
|
||||||
T *value;
|
T *value;
|
||||||
Unioned other;
|
Unioned other;
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
HeapPtr() : value(NULL) {}
|
EncapsulatedPtr() : value(NULL) {}
|
||||||
explicit HeapPtr(T *v) : value(v) { post(); }
|
explicit EncapsulatedPtr(T *v) : value(v) {}
|
||||||
explicit HeapPtr(const HeapPtr<T> &v) : value(v.value) { post(); }
|
explicit EncapsulatedPtr(const EncapsulatedPtr<T> &v) : value(v.value) {}
|
||||||
|
|
||||||
~HeapPtr() { pre(); }
|
~EncapsulatedPtr() { 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. */
|
/* Use to set the pointer to NULL. */
|
||||||
void clear() {
|
void clear() {
|
||||||
pre();
|
pre();
|
||||||
value = NULL;
|
value = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
EncapsulatedPtr<T, Unioned> &operator=(T *v) {
|
||||||
|
pre();
|
||||||
|
JS_ASSERT(!IsPoisonedPtr<T>(v));
|
||||||
|
value = v;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
EncapsulatedPtr<T, Unioned> &operator=(const EncapsulatedPtr<T> &v) {
|
||||||
|
pre();
|
||||||
|
JS_ASSERT(!IsPoisonedPtr<T>(v.value));
|
||||||
|
value = v.value;
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Use this if the automatic coercion to T* isn't working. */
|
/* Use this if the automatic coercion to T* isn't working. */
|
||||||
|
@ -192,30 +166,48 @@ class HeapPtr
|
||||||
|
|
||||||
Unioned *unsafeGetUnioned() { return &other; }
|
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; }
|
||||||
T *operator->() const { return value; }
|
T *operator->() const { return value; }
|
||||||
|
|
||||||
operator T*() const { return value; }
|
operator T*() const { return value; }
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
void pre() { T::writeBarrierPre(value); }
|
void pre() { T::writeBarrierPre(value); }
|
||||||
void post() { T::writeBarrierPost(value, (void *)&value); }
|
};
|
||||||
|
|
||||||
|
template <class T, class Unioned = uintptr_t>
|
||||||
|
class HeapPtr : public EncapsulatedPtr<T, Unioned>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
HeapPtr() : EncapsulatedPtr<T>(NULL) {}
|
||||||
|
explicit HeapPtr(T *v) : EncapsulatedPtr<T>(v) { post(); }
|
||||||
|
explicit HeapPtr(const HeapPtr<T> &v)
|
||||||
|
: EncapsulatedPtr<T>(v) { post(); }
|
||||||
|
|
||||||
|
void init(T *v) {
|
||||||
|
JS_ASSERT(!IsPoisonedPtr<T>(v));
|
||||||
|
this->value = v;
|
||||||
|
post();
|
||||||
|
}
|
||||||
|
|
||||||
|
HeapPtr<T, Unioned> &operator=(T *v) {
|
||||||
|
this->pre();
|
||||||
|
JS_ASSERT(!IsPoisonedPtr<T>(v));
|
||||||
|
this->value = v;
|
||||||
|
post();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
HeapPtr<T, Unioned> &operator=(const HeapPtr<T> &v) {
|
||||||
|
this->pre();
|
||||||
|
JS_ASSERT(!IsPoisonedPtr<T>(v.value));
|
||||||
|
this->value = v.value;
|
||||||
|
post();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void post() { T::writeBarrierPost(this->value, (void *)&this->value); }
|
||||||
|
|
||||||
/* Make this friend so it can access pre() and post(). */
|
/* Make this friend so it can access pre() and post(). */
|
||||||
template<class T1, class T2>
|
template<class T1, class T2>
|
||||||
|
@ -225,6 +217,41 @@ class HeapPtr
|
||||||
HeapPtr<T2> &v2, T2 *val2);
|
HeapPtr<T2> &v2, T2 *val2);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
class RelocatablePtr : public EncapsulatedPtr<T>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
RelocatablePtr() : EncapsulatedPtr<T>(NULL) {}
|
||||||
|
explicit RelocatablePtr(T *v) : EncapsulatedPtr<T>(v) { post(); }
|
||||||
|
explicit RelocatablePtr(const RelocatablePtr<T> &v)
|
||||||
|
: EncapsulatedPtr<T>(v) { post(); }
|
||||||
|
|
||||||
|
~RelocatablePtr() {
|
||||||
|
this->pre();
|
||||||
|
relocate();
|
||||||
|
}
|
||||||
|
|
||||||
|
RelocatablePtr<T> &operator=(T *v) {
|
||||||
|
this->pre();
|
||||||
|
JS_ASSERT(!IsPoisonedPtr<T>(v));
|
||||||
|
this->value = v;
|
||||||
|
post();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
RelocatablePtr<T> &operator=(const RelocatablePtr<T> &v) {
|
||||||
|
this->pre();
|
||||||
|
JS_ASSERT(!IsPoisonedPtr<T>(v.value));
|
||||||
|
this->value = v.value;
|
||||||
|
post();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void post() { T::writeBarrierRelocPost(this->value, (void *)&this->value); }
|
||||||
|
void relocate() { T::writeBarrierRelocated(this->value, (void *)&this->value); }
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is a hack for RegExpStatics::updateFromMatch. It allows us to do two
|
* 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.
|
* barriers with only one branch to check if we're in an incremental GC.
|
||||||
|
@ -249,7 +276,9 @@ struct Shape;
|
||||||
class BaseShape;
|
class BaseShape;
|
||||||
namespace types { struct TypeObject; }
|
namespace types { struct TypeObject; }
|
||||||
|
|
||||||
typedef HeapPtr<JSAtom> HeapPtrAtom;
|
typedef RelocatablePtr<JSObject> RelocatablePtrObject;
|
||||||
|
typedef RelocatablePtr<JSScript> RelocatablePtrScript;
|
||||||
|
|
||||||
typedef HeapPtr<JSObject> HeapPtrObject;
|
typedef HeapPtr<JSObject> HeapPtrObject;
|
||||||
typedef HeapPtr<JSFunction> HeapPtrFunction;
|
typedef HeapPtr<JSFunction> HeapPtrFunction;
|
||||||
typedef HeapPtr<JSString> HeapPtrString;
|
typedef HeapPtr<JSString> HeapPtrString;
|
||||||
|
@ -272,9 +301,9 @@ struct HeapPtrHasher
|
||||||
|
|
||||||
/* Specialized hashing policy for HeapPtrs. */
|
/* Specialized hashing policy for HeapPtrs. */
|
||||||
template <class T>
|
template <class T>
|
||||||
struct DefaultHasher< HeapPtr<T> >: HeapPtrHasher<T> { };
|
struct DefaultHasher< HeapPtr<T> > : HeapPtrHasher<T> { };
|
||||||
|
|
||||||
class EncapsulatedValue
|
class EncapsulatedValue : public ValueOperations<EncapsulatedValue>
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
Value value;
|
Value value;
|
||||||
|
@ -292,47 +321,27 @@ class EncapsulatedValue
|
||||||
~EncapsulatedValue() {}
|
~EncapsulatedValue() {}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
bool operator==(const EncapsulatedValue &v) const { return value == v.value; }
|
||||||
|
bool operator!=(const EncapsulatedValue &v) const { return value != v.value; }
|
||||||
|
|
||||||
const Value &get() const { return value; }
|
const Value &get() const { return value; }
|
||||||
Value *unsafeGet() { return &value; }
|
Value *unsafeGet() { return &value; }
|
||||||
operator const Value &() const { 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(); }
|
JSGCTraceKind gcKind() const { return value.gcKind(); }
|
||||||
|
|
||||||
uint64_t asRawBits() const { return value.asRawBits(); }
|
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(const Value &v);
|
||||||
static inline void writeBarrierPre(JSCompartment *comp, const Value &v);
|
static inline void writeBarrierPre(JSCompartment *comp, const Value &v);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
inline void pre();
|
inline void pre();
|
||||||
inline void pre(JSCompartment *comp);
|
inline void pre(JSCompartment *comp);
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class ValueOperations<EncapsulatedValue>;
|
||||||
|
const Value * extract() const { return &value; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class HeapValue : public EncapsulatedValue
|
class HeapValue : public EncapsulatedValue
|
||||||
|
@ -357,14 +366,31 @@ class HeapValue : public EncapsulatedValue
|
||||||
*/
|
*/
|
||||||
inline void set(JSCompartment *comp, const Value &v);
|
inline void set(JSCompartment *comp, const Value &v);
|
||||||
|
|
||||||
static inline void writeBarrierPost(const Value &v, void *addr);
|
static inline void writeBarrierPost(const Value &v, Value *addr);
|
||||||
static inline void writeBarrierPost(JSCompartment *comp, const Value &v, void *addr);
|
static inline void writeBarrierPost(JSCompartment *comp, const Value &v, Value *addr);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
inline void post();
|
inline void post();
|
||||||
inline void post(JSCompartment *comp);
|
inline void post(JSCompartment *comp);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class RelocatableValue : public EncapsulatedValue
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit inline RelocatableValue();
|
||||||
|
explicit inline RelocatableValue(const Value &v);
|
||||||
|
explicit inline RelocatableValue(const RelocatableValue &v);
|
||||||
|
inline ~RelocatableValue();
|
||||||
|
|
||||||
|
inline RelocatableValue &operator=(const Value &v);
|
||||||
|
inline RelocatableValue &operator=(const RelocatableValue &v);
|
||||||
|
|
||||||
|
private:
|
||||||
|
inline void post();
|
||||||
|
inline void post(JSCompartment *comp);
|
||||||
|
inline void relocate();
|
||||||
|
};
|
||||||
|
|
||||||
class HeapSlot : public EncapsulatedValue
|
class HeapSlot : public EncapsulatedValue
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
@ -401,7 +427,7 @@ class HeapSlot : public EncapsulatedValue
|
||||||
* Run a post write barrier that encompasses multiple contiguous slots in a
|
* Run a post write barrier that encompasses multiple contiguous slots in a
|
||||||
* single step.
|
* single step.
|
||||||
*/
|
*/
|
||||||
static inline void
|
inline void
|
||||||
SlotRangeWriteBarrierPost(JSCompartment *comp, JSObject *obj, uint32_t start, uint32_t count)
|
SlotRangeWriteBarrierPost(JSCompartment *comp, JSObject *obj, uint32_t start, uint32_t count)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -414,6 +440,14 @@ Valueify(const EncapsulatedValue *array)
|
||||||
return (const Value *)array;
|
return (const Value *)array;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline HeapValue *
|
||||||
|
HeapValueify(Value *v)
|
||||||
|
{
|
||||||
|
JS_STATIC_ASSERT(sizeof(HeapValue) == sizeof(Value));
|
||||||
|
JS_STATIC_ASSERT(sizeof(HeapSlot) == sizeof(Value));
|
||||||
|
return (HeapValue *)v;
|
||||||
|
}
|
||||||
|
|
||||||
class HeapSlotArray
|
class HeapSlotArray
|
||||||
{
|
{
|
||||||
HeapSlot *array;
|
HeapSlot *array;
|
||||||
|
@ -428,21 +462,20 @@ class HeapSlotArray
|
||||||
HeapSlotArray operator +(uint32_t offset) const { return HeapSlotArray(array + offset); }
|
HeapSlotArray operator +(uint32_t offset) const { return HeapSlotArray(array + offset); }
|
||||||
};
|
};
|
||||||
|
|
||||||
class HeapId
|
class EncapsulatedId
|
||||||
{
|
{
|
||||||
|
protected:
|
||||||
jsid value;
|
jsid value;
|
||||||
|
|
||||||
|
explicit EncapsulatedId() : value(JSID_VOID) {}
|
||||||
|
explicit inline EncapsulatedId(jsid id) : value(id) {}
|
||||||
|
~EncapsulatedId() {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
EncapsulatedId(const EncapsulatedId &v) MOZ_DELETE;
|
||||||
|
EncapsulatedId &operator=(const EncapsulatedId &v) MOZ_DELETE;
|
||||||
|
|
||||||
public:
|
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; }
|
||||||
bool operator!=(jsid id) const { return value != id; }
|
bool operator!=(jsid id) const { return value != id; }
|
||||||
|
|
||||||
|
@ -450,11 +483,37 @@ class HeapId
|
||||||
jsid *unsafeGet() { return &value; }
|
jsid *unsafeGet() { return &value; }
|
||||||
operator jsid() const { return value; }
|
operator jsid() const { return value; }
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
inline void pre();
|
inline void pre();
|
||||||
|
};
|
||||||
|
|
||||||
|
class RelocatableId : public EncapsulatedId
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit RelocatableId() : EncapsulatedId() {}
|
||||||
|
explicit inline RelocatableId(jsid id) : EncapsulatedId(id) {}
|
||||||
|
inline ~RelocatableId();
|
||||||
|
|
||||||
|
inline RelocatableId &operator=(jsid id);
|
||||||
|
inline RelocatableId &operator=(const RelocatableId &v);
|
||||||
|
};
|
||||||
|
|
||||||
|
class HeapId : public EncapsulatedId
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit HeapId() : EncapsulatedId() {}
|
||||||
|
explicit inline HeapId(jsid id);
|
||||||
|
inline ~HeapId();
|
||||||
|
|
||||||
|
inline void init(jsid id);
|
||||||
|
|
||||||
|
inline HeapId &operator=(jsid id);
|
||||||
|
inline HeapId &operator=(const HeapId &v);
|
||||||
|
|
||||||
|
private:
|
||||||
inline void post();
|
inline void post();
|
||||||
|
|
||||||
HeapId(const HeapId &v);
|
HeapId(const HeapId &v) MOZ_DELETE;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -488,7 +547,7 @@ class ReadBarriered
|
||||||
T &operator*() const { return *get(); }
|
T &operator*() const { return *get(); }
|
||||||
T *operator->() const { return get(); }
|
T *operator->() const { return get(); }
|
||||||
|
|
||||||
T *unsafeGet() { return value; }
|
T **unsafeGet() { return &value; }
|
||||||
|
|
||||||
void set(T *v) { value = v; }
|
void set(T *v) { value = v; }
|
||||||
|
|
||||||
|
@ -504,6 +563,7 @@ class ReadBarrieredValue
|
||||||
ReadBarrieredValue(const Value &value) : value(value) {}
|
ReadBarrieredValue(const Value &value) : value(value) {}
|
||||||
|
|
||||||
inline const Value &get() const;
|
inline const Value &get() const;
|
||||||
|
Value *unsafeGet() { return &value; }
|
||||||
inline operator const Value &() const;
|
inline operator const Value &() const;
|
||||||
|
|
||||||
inline JSObject &toObject() const;
|
inline JSObject &toObject() const;
|
||||||
|
@ -511,11 +571,11 @@ class ReadBarrieredValue
|
||||||
|
|
||||||
namespace tl {
|
namespace tl {
|
||||||
|
|
||||||
template <class T> struct IsPostBarrieredType<HeapPtr<T> > {
|
template <class T> struct IsRelocatableHeapType<HeapPtr<T> >
|
||||||
static const bool result = true; };
|
{ static const bool result = false; };
|
||||||
template <> struct IsPostBarrieredType<HeapSlot> { static const bool result = true; };
|
template <> struct IsRelocatableHeapType<HeapSlot> { static const bool result = false; };
|
||||||
template <> struct IsPostBarrieredType<HeapValue> { static const bool result = true; };
|
template <> struct IsRelocatableHeapType<HeapValue> { static const bool result = false; };
|
||||||
template <> struct IsPostBarrieredType<HeapId> { static const bool result = true; };
|
template <> struct IsRelocatableHeapType<HeapId> { static const bool result = false; };
|
||||||
|
|
||||||
} /* namespace tl */
|
} /* namespace tl */
|
||||||
} /* namespace js */
|
} /* namespace js */
|
||||||
|
|
|
@ -0,0 +1,978 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 8; 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/. */
|
||||||
|
|
||||||
|
#ifndef gc_heap_h___
|
||||||
|
#define gc_heap_h___
|
||||||
|
|
||||||
|
#include "mozilla/Attributes.h"
|
||||||
|
#include "mozilla/StandardInteger.h"
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include "jstypes.h"
|
||||||
|
#include "jsutil.h"
|
||||||
|
|
||||||
|
#include "ds/BitArray.h"
|
||||||
|
|
||||||
|
struct JSCompartment;
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
struct JSRuntime;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace js {
|
||||||
|
|
||||||
|
class FreeOp;
|
||||||
|
|
||||||
|
namespace gc {
|
||||||
|
|
||||||
|
struct Arena;
|
||||||
|
struct ArenaHeader;
|
||||||
|
struct Chunk;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This must be an upper bound, but we do not need the least upper bound, so
|
||||||
|
* we just exclude non-background objects.
|
||||||
|
*/
|
||||||
|
static const size_t MAX_BACKGROUND_FINALIZE_KINDS = FINALIZE_LIMIT - FINALIZE_OBJECT_LIMIT / 2;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
MOZ_ALWAYS_INLINE bool isMarked(uint32_t color = BLACK) const;
|
||||||
|
MOZ_ALWAYS_INLINE bool markIfUnmarked(uint32_t color = BLACK) const;
|
||||||
|
MOZ_ALWAYS_INLINE void unmark(uint32_t color) const;
|
||||||
|
|
||||||
|
inline JSCompartment *compartment() const;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
inline bool isAligned() const;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Page size is 4096 by default, except for SPARC, where it is 8192.
|
||||||
|
* Note: Do not use JS_CPU_SPARC here, this header is used outside JS.
|
||||||
|
* Bug 692267: Move page size definition to gc/Memory.h and include it
|
||||||
|
* directly once jsgc.h is no longer an installed header.
|
||||||
|
*/
|
||||||
|
#if defined(SOLARIS) && (defined(__sparc) || defined(__sparcv9))
|
||||||
|
const size_t PageShift = 13;
|
||||||
|
#else
|
||||||
|
const size_t PageShift = 12;
|
||||||
|
#endif
|
||||||
|
const size_t PageSize = size_t(1) << PageShift;
|
||||||
|
|
||||||
|
const size_t ChunkShift = 20;
|
||||||
|
const size_t ChunkSize = size_t(1) << ChunkShift;
|
||||||
|
const size_t ChunkMask = ChunkSize - 1;
|
||||||
|
|
||||||
|
const size_t ArenaShift = PageShift;
|
||||||
|
const size_t ArenaSize = PageSize;
|
||||||
|
const size_t ArenaMask = ArenaSize - 1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is the maximum number of arenas we allow in the FreeCommitted state
|
||||||
|
* before we trigger a GC_SHRINK to release free arenas to the OS.
|
||||||
|
*/
|
||||||
|
const static uint32_t FreeCommittedArenasThreshold = (32 << 20) / ArenaSize;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The mark bitmap has one bit per each GC cell. For multi-cell GC things this
|
||||||
|
* wastes space but allows to avoid expensive devisions by thing's size when
|
||||||
|
* accessing the bitmap. In addition this allows to use some bits for colored
|
||||||
|
* marking during the cycle GC.
|
||||||
|
*/
|
||||||
|
const size_t ArenaCellCount = size_t(1) << (ArenaShift - Cell::CellShift);
|
||||||
|
const size_t ArenaBitmapBits = ArenaCellCount;
|
||||||
|
const size_t ArenaBitmapBytes = ArenaBitmapBits / 8;
|
||||||
|
const size_t ArenaBitmapWords = ArenaBitmapBits / JS_BITS_PER_WORD;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A FreeSpan represents a contiguous sequence of free cells in an Arena.
|
||||||
|
* |first| is the address of the first free cell in the span. |last| is the
|
||||||
|
* address of the last free cell in the span. This last cell holds a FreeSpan
|
||||||
|
* data structure for the next span unless this is the last span on the list
|
||||||
|
* of spans in the arena. For this last span |last| points to the last byte of
|
||||||
|
* the last thing in the arena and no linkage is stored there, so
|
||||||
|
* |last| == arenaStart + ArenaSize - 1. If the space at the arena end is
|
||||||
|
* fully used this last span is empty and |first| == |last + 1|.
|
||||||
|
*
|
||||||
|
* Thus |first| < |last| implies that we have either the last span with at least
|
||||||
|
* one element or that the span is not the last and contains at least 2
|
||||||
|
* elements. In both cases to allocate a thing from this span we need simply
|
||||||
|
* to increment |first| by the allocation size.
|
||||||
|
*
|
||||||
|
* |first| == |last| implies that we have a one element span that records the
|
||||||
|
* next span. So to allocate from it we need to update the span list head
|
||||||
|
* with a copy of the span stored at |last| address so the following
|
||||||
|
* allocations will use that span.
|
||||||
|
*
|
||||||
|
* |first| > |last| implies that we have an empty last span and the arena is
|
||||||
|
* fully used.
|
||||||
|
*
|
||||||
|
* Also only for the last span (|last| & 1)! = 0 as all allocation sizes are
|
||||||
|
* multiples of Cell::CellSize.
|
||||||
|
*/
|
||||||
|
struct FreeSpan
|
||||||
|
{
|
||||||
|
uintptr_t first;
|
||||||
|
uintptr_t last;
|
||||||
|
|
||||||
|
public:
|
||||||
|
FreeSpan() {}
|
||||||
|
|
||||||
|
FreeSpan(uintptr_t first, uintptr_t last)
|
||||||
|
: first(first), last(last) {
|
||||||
|
checkSpan();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* To minimize the size of the arena header the first span is encoded
|
||||||
|
* there as offsets from the arena start.
|
||||||
|
*/
|
||||||
|
static size_t encodeOffsets(size_t firstOffset, size_t lastOffset) {
|
||||||
|
/* Check that we can pack the offsets into uint16. */
|
||||||
|
JS_STATIC_ASSERT(ArenaShift < 16);
|
||||||
|
JS_ASSERT(firstOffset <= ArenaSize);
|
||||||
|
JS_ASSERT(lastOffset < ArenaSize);
|
||||||
|
JS_ASSERT(firstOffset <= ((lastOffset + 1) & ~size_t(1)));
|
||||||
|
return firstOffset | (lastOffset << 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Encoded offsets for a full arena when its first span is the last one
|
||||||
|
* and empty.
|
||||||
|
*/
|
||||||
|
static const size_t FullArenaOffsets = ArenaSize | ((ArenaSize - 1) << 16);
|
||||||
|
|
||||||
|
static FreeSpan decodeOffsets(uintptr_t arenaAddr, size_t offsets) {
|
||||||
|
JS_ASSERT(!(arenaAddr & ArenaMask));
|
||||||
|
|
||||||
|
size_t firstOffset = offsets & 0xFFFF;
|
||||||
|
size_t lastOffset = offsets >> 16;
|
||||||
|
JS_ASSERT(firstOffset <= ArenaSize);
|
||||||
|
JS_ASSERT(lastOffset < ArenaSize);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We must not use | when calculating first as firstOffset is
|
||||||
|
* ArenaMask + 1 for the empty span.
|
||||||
|
*/
|
||||||
|
return FreeSpan(arenaAddr + firstOffset, arenaAddr | lastOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void initAsEmpty(uintptr_t arenaAddr = 0) {
|
||||||
|
JS_ASSERT(!(arenaAddr & ArenaMask));
|
||||||
|
first = arenaAddr + ArenaSize;
|
||||||
|
last = arenaAddr | (ArenaSize - 1);
|
||||||
|
JS_ASSERT(isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isEmpty() const {
|
||||||
|
checkSpan();
|
||||||
|
return first > last;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hasNext() const {
|
||||||
|
checkSpan();
|
||||||
|
return !(last & uintptr_t(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
const FreeSpan *nextSpan() const {
|
||||||
|
JS_ASSERT(hasNext());
|
||||||
|
return reinterpret_cast<FreeSpan *>(last);
|
||||||
|
}
|
||||||
|
|
||||||
|
FreeSpan *nextSpanUnchecked(size_t thingSize) const {
|
||||||
|
#ifdef DEBUG
|
||||||
|
uintptr_t lastOffset = last & ArenaMask;
|
||||||
|
JS_ASSERT(!(lastOffset & 1));
|
||||||
|
JS_ASSERT((ArenaSize - lastOffset) % thingSize == 0);
|
||||||
|
#endif
|
||||||
|
return reinterpret_cast<FreeSpan *>(last);
|
||||||
|
}
|
||||||
|
|
||||||
|
uintptr_t arenaAddressUnchecked() const {
|
||||||
|
return last & ~ArenaMask;
|
||||||
|
}
|
||||||
|
|
||||||
|
uintptr_t arenaAddress() const {
|
||||||
|
checkSpan();
|
||||||
|
return arenaAddressUnchecked();
|
||||||
|
}
|
||||||
|
|
||||||
|
ArenaHeader *arenaHeader() const {
|
||||||
|
return reinterpret_cast<ArenaHeader *>(arenaAddress());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isSameNonEmptySpan(const FreeSpan *another) const {
|
||||||
|
JS_ASSERT(!isEmpty());
|
||||||
|
JS_ASSERT(!another->isEmpty());
|
||||||
|
return first == another->first && last == another->last;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isWithinArena(uintptr_t arenaAddr) const {
|
||||||
|
JS_ASSERT(!(arenaAddr & ArenaMask));
|
||||||
|
|
||||||
|
/* Return true for the last empty span as well. */
|
||||||
|
return arenaAddress() == arenaAddr;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t encodeAsOffsets() const {
|
||||||
|
/*
|
||||||
|
* We must use first - arenaAddress(), not first & ArenaMask as
|
||||||
|
* first == ArenaMask + 1 for an empty span.
|
||||||
|
*/
|
||||||
|
uintptr_t arenaAddr = arenaAddress();
|
||||||
|
return encodeOffsets(first - arenaAddr, last & ArenaMask);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* See comments before FreeSpan for details. */
|
||||||
|
MOZ_ALWAYS_INLINE void *allocate(size_t thingSize) {
|
||||||
|
JS_ASSERT(thingSize % Cell::CellSize == 0);
|
||||||
|
checkSpan();
|
||||||
|
uintptr_t thing = first;
|
||||||
|
if (thing < last) {
|
||||||
|
/* Bump-allocate from the current span. */
|
||||||
|
first = thing + thingSize;
|
||||||
|
} else if (JS_LIKELY(thing == last)) {
|
||||||
|
/*
|
||||||
|
* Move to the next span. We use JS_LIKELY as without PGO
|
||||||
|
* compilers mis-predict == here as unlikely to succeed.
|
||||||
|
*/
|
||||||
|
*this = *reinterpret_cast<FreeSpan *>(thing);
|
||||||
|
} else {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
checkSpan();
|
||||||
|
return reinterpret_cast<void *>(thing);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* A version of allocate when we know that the span is not empty. */
|
||||||
|
MOZ_ALWAYS_INLINE void *infallibleAllocate(size_t thingSize) {
|
||||||
|
JS_ASSERT(thingSize % Cell::CellSize == 0);
|
||||||
|
checkSpan();
|
||||||
|
uintptr_t thing = first;
|
||||||
|
if (thing < last) {
|
||||||
|
first = thing + thingSize;
|
||||||
|
} else {
|
||||||
|
JS_ASSERT(thing == last);
|
||||||
|
*this = *reinterpret_cast<FreeSpan *>(thing);
|
||||||
|
}
|
||||||
|
checkSpan();
|
||||||
|
return reinterpret_cast<void *>(thing);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allocate from a newly allocated arena. We do not move the free list
|
||||||
|
* from the arena. Rather we set the arena up as fully used during the
|
||||||
|
* initialization so to allocate we simply return the first thing in the
|
||||||
|
* arena and set the free list to point to the second.
|
||||||
|
*/
|
||||||
|
MOZ_ALWAYS_INLINE void *allocateFromNewArena(uintptr_t arenaAddr, size_t firstThingOffset,
|
||||||
|
size_t thingSize) {
|
||||||
|
JS_ASSERT(!(arenaAddr & ArenaMask));
|
||||||
|
uintptr_t thing = arenaAddr | firstThingOffset;
|
||||||
|
first = thing + thingSize;
|
||||||
|
last = arenaAddr | ArenaMask;
|
||||||
|
checkSpan();
|
||||||
|
return reinterpret_cast<void *>(thing);
|
||||||
|
}
|
||||||
|
|
||||||
|
void checkSpan() const {
|
||||||
|
#ifdef DEBUG
|
||||||
|
/* We do not allow spans at the end of the address space. */
|
||||||
|
JS_ASSERT(last != uintptr_t(-1));
|
||||||
|
JS_ASSERT(first);
|
||||||
|
JS_ASSERT(last);
|
||||||
|
JS_ASSERT(first - 1 <= last);
|
||||||
|
uintptr_t arenaAddr = arenaAddressUnchecked();
|
||||||
|
if (last & 1) {
|
||||||
|
/* The span is the last. */
|
||||||
|
JS_ASSERT((last & ArenaMask) == ArenaMask);
|
||||||
|
|
||||||
|
if (first - 1 == last) {
|
||||||
|
/* The span is last and empty. The above start != 0 check
|
||||||
|
* implies that we are not at the end of the address space.
|
||||||
|
*/
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
size_t spanLength = last - first + 1;
|
||||||
|
JS_ASSERT(spanLength % Cell::CellSize == 0);
|
||||||
|
|
||||||
|
/* Start and end must belong to the same arena. */
|
||||||
|
JS_ASSERT((first & ~ArenaMask) == arenaAddr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The span is not the last and we have more spans to follow. */
|
||||||
|
JS_ASSERT(first <= last);
|
||||||
|
size_t spanLengthWithoutOneThing = last - first;
|
||||||
|
JS_ASSERT(spanLengthWithoutOneThing % Cell::CellSize == 0);
|
||||||
|
|
||||||
|
JS_ASSERT((first & ~ArenaMask) == arenaAddr);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If there is not enough space before the arena end to allocate one
|
||||||
|
* more thing, then the span must be marked as the last one to avoid
|
||||||
|
* storing useless empty span reference.
|
||||||
|
*/
|
||||||
|
size_t beforeTail = ArenaSize - (last & ArenaMask);
|
||||||
|
JS_ASSERT(beforeTail >= sizeof(FreeSpan) + Cell::CellSize);
|
||||||
|
|
||||||
|
FreeSpan *next = reinterpret_cast<FreeSpan *>(last);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The GC things on the list of free spans come from one arena
|
||||||
|
* and the spans are linked in ascending address order with
|
||||||
|
* at least one non-free thing between spans.
|
||||||
|
*/
|
||||||
|
JS_ASSERT(last < next->first);
|
||||||
|
JS_ASSERT(arenaAddr == next->arenaAddressUnchecked());
|
||||||
|
|
||||||
|
if (next->first > next->last) {
|
||||||
|
/*
|
||||||
|
* The next span is the empty span that terminates the list for
|
||||||
|
* arenas that do not have any free things at the end.
|
||||||
|
*/
|
||||||
|
JS_ASSERT(next->first - 1 == next->last);
|
||||||
|
JS_ASSERT(arenaAddr + ArenaSize == next->first);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Every arena has a header. */
|
||||||
|
struct ArenaHeader
|
||||||
|
{
|
||||||
|
friend struct FreeLists;
|
||||||
|
|
||||||
|
JSCompartment *compartment;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ArenaHeader::next has two purposes: when unallocated, it points to the
|
||||||
|
* next available Arena's header. When allocated, it points to the next
|
||||||
|
* arena of the same size class and compartment.
|
||||||
|
*/
|
||||||
|
ArenaHeader *next;
|
||||||
|
|
||||||
|
private:
|
||||||
|
/*
|
||||||
|
* The first span of free things in the arena. We encode it as the start
|
||||||
|
* and end offsets within the arena, not as FreeSpan structure, to
|
||||||
|
* minimize the header size.
|
||||||
|
*/
|
||||||
|
size_t firstFreeSpanOffsets;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* One of AllocKind constants or FINALIZE_LIMIT when the arena does not
|
||||||
|
* contain any GC things and is on the list of empty arenas in the GC
|
||||||
|
* chunk. The latter allows to quickly check if the arena is allocated
|
||||||
|
* during the conservative GC scanning without searching the arena in the
|
||||||
|
* list.
|
||||||
|
*/
|
||||||
|
size_t allocKind : 8;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When recursive marking uses too much stack the marking is delayed and
|
||||||
|
* the corresponding arenas are put into a stack using the following field
|
||||||
|
* as a linkage. To distinguish the bottom of the stack from the arenas
|
||||||
|
* not present in the stack we use an extra flag to tag arenas on the
|
||||||
|
* stack.
|
||||||
|
*
|
||||||
|
* Delayed marking is also used for arenas that we allocate into during an
|
||||||
|
* incremental GC. In this case, we intend to mark all the objects in the
|
||||||
|
* arena, and it's faster to do this marking in bulk.
|
||||||
|
*
|
||||||
|
* To minimize the ArenaHeader size we record the next delayed marking
|
||||||
|
* linkage as arenaAddress() >> ArenaShift and pack it with the allocKind
|
||||||
|
* field and hasDelayedMarking flag. We use 8 bits for the allocKind, not
|
||||||
|
* ArenaShift - 1, so the compiler can use byte-level memory instructions
|
||||||
|
* to access it.
|
||||||
|
*/
|
||||||
|
public:
|
||||||
|
size_t hasDelayedMarking : 1;
|
||||||
|
size_t allocatedDuringIncremental : 1;
|
||||||
|
size_t markOverflow : 1;
|
||||||
|
size_t nextDelayedMarking : JS_BITS_PER_WORD - 8 - 1 - 1 - 1;
|
||||||
|
|
||||||
|
static void staticAsserts() {
|
||||||
|
/* We must be able to fit the allockind into uint8_t. */
|
||||||
|
JS_STATIC_ASSERT(FINALIZE_LIMIT <= 255);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* nextDelayedMarkingpacking assumes that ArenaShift has enough bits
|
||||||
|
* to cover allocKind and hasDelayedMarking.
|
||||||
|
*/
|
||||||
|
JS_STATIC_ASSERT(ArenaShift >= 8 + 1 + 1 + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uintptr_t address() const;
|
||||||
|
inline Chunk *chunk() const;
|
||||||
|
|
||||||
|
bool allocated() const {
|
||||||
|
JS_ASSERT(allocKind <= size_t(FINALIZE_LIMIT));
|
||||||
|
return allocKind < size_t(FINALIZE_LIMIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void init(JSCompartment *comp, AllocKind kind) {
|
||||||
|
JS_ASSERT(!allocated());
|
||||||
|
JS_ASSERT(!markOverflow);
|
||||||
|
JS_ASSERT(!allocatedDuringIncremental);
|
||||||
|
JS_ASSERT(!hasDelayedMarking);
|
||||||
|
compartment = comp;
|
||||||
|
|
||||||
|
JS_STATIC_ASSERT(FINALIZE_LIMIT <= 255);
|
||||||
|
allocKind = size_t(kind);
|
||||||
|
|
||||||
|
/* See comments in FreeSpan::allocateFromNewArena. */
|
||||||
|
firstFreeSpanOffsets = FreeSpan::FullArenaOffsets;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setAsNotAllocated() {
|
||||||
|
allocKind = size_t(FINALIZE_LIMIT);
|
||||||
|
markOverflow = 0;
|
||||||
|
allocatedDuringIncremental = 0;
|
||||||
|
hasDelayedMarking = 0;
|
||||||
|
nextDelayedMarking = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uintptr_t arenaAddress() const;
|
||||||
|
inline Arena *getArena();
|
||||||
|
|
||||||
|
AllocKind getAllocKind() const {
|
||||||
|
JS_ASSERT(allocated());
|
||||||
|
return AllocKind(allocKind);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline size_t getThingSize() const;
|
||||||
|
|
||||||
|
bool hasFreeThings() const {
|
||||||
|
return firstFreeSpanOffsets != FreeSpan::FullArenaOffsets;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool isEmpty() const;
|
||||||
|
|
||||||
|
void setAsFullyUsed() {
|
||||||
|
firstFreeSpanOffsets = FreeSpan::FullArenaOffsets;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline FreeSpan getFirstFreeSpan() const;
|
||||||
|
inline void setFirstFreeSpan(const FreeSpan *span);
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
void checkSynchronizedWithFreeList() const;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
inline ArenaHeader *getNextDelayedMarking() const;
|
||||||
|
inline void setNextDelayedMarking(ArenaHeader *aheader);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Arena
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Layout of an arena:
|
||||||
|
* An arena is 4K in size and 4K-aligned. It starts with the ArenaHeader
|
||||||
|
* descriptor followed by some pad bytes. The remainder of the arena is
|
||||||
|
* filled with the array of T things. The pad bytes ensure that the thing
|
||||||
|
* array ends exactly at the end of the arena.
|
||||||
|
*
|
||||||
|
* +-------------+-----+----+----+-----+----+
|
||||||
|
* | ArenaHeader | pad | T0 | T1 | ... | Tn |
|
||||||
|
* +-------------+-----+----+----+-----+----+
|
||||||
|
*
|
||||||
|
* <----------------------------------------> = ArenaSize bytes
|
||||||
|
* <-------------------> = first thing offset
|
||||||
|
*/
|
||||||
|
ArenaHeader aheader;
|
||||||
|
uint8_t data[ArenaSize - sizeof(ArenaHeader)];
|
||||||
|
|
||||||
|
private:
|
||||||
|
static JS_FRIEND_DATA(const uint32_t) ThingSizes[];
|
||||||
|
static JS_FRIEND_DATA(const uint32_t) FirstThingOffsets[];
|
||||||
|
|
||||||
|
public:
|
||||||
|
static void staticAsserts();
|
||||||
|
|
||||||
|
static size_t thingSize(AllocKind kind) {
|
||||||
|
return ThingSizes[kind];
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t firstThingOffset(AllocKind kind) {
|
||||||
|
return FirstThingOffsets[kind];
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t thingsPerArena(size_t thingSize) {
|
||||||
|
JS_ASSERT(thingSize % Cell::CellSize == 0);
|
||||||
|
|
||||||
|
/* We should be able to fit FreeSpan in any GC thing. */
|
||||||
|
JS_ASSERT(thingSize >= sizeof(FreeSpan));
|
||||||
|
|
||||||
|
return (ArenaSize - sizeof(ArenaHeader)) / thingSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t thingsSpan(size_t thingSize) {
|
||||||
|
return thingsPerArena(thingSize) * thingSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool isAligned(uintptr_t thing, size_t thingSize) {
|
||||||
|
/* Things ends at the arena end. */
|
||||||
|
uintptr_t tailOffset = (ArenaSize - thing) & ArenaMask;
|
||||||
|
return tailOffset % thingSize == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uintptr_t address() const {
|
||||||
|
return aheader.address();
|
||||||
|
}
|
||||||
|
|
||||||
|
uintptr_t thingsStart(AllocKind thingKind) {
|
||||||
|
return address() | firstThingOffset(thingKind);
|
||||||
|
}
|
||||||
|
|
||||||
|
uintptr_t thingsEnd() {
|
||||||
|
return address() + ArenaSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
bool finalize(FreeOp *fop, AllocKind thingKind, size_t thingSize);
|
||||||
|
};
|
||||||
|
|
||||||
|
inline size_t
|
||||||
|
ArenaHeader::getThingSize() const
|
||||||
|
{
|
||||||
|
JS_ASSERT(allocated());
|
||||||
|
return Arena::thingSize(getAllocKind());
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The chunk header (located at the end of the chunk to preserve arena alignment). */
|
||||||
|
struct ChunkInfo
|
||||||
|
{
|
||||||
|
Chunk *next;
|
||||||
|
Chunk **prevp;
|
||||||
|
|
||||||
|
/* Free arenas are linked together with aheader.next. */
|
||||||
|
ArenaHeader *freeArenasHead;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Decommitted arenas are tracked by a bitmap in the chunk header. We use
|
||||||
|
* this offset to start our search iteration close to a decommitted arena
|
||||||
|
* that we can allocate.
|
||||||
|
*/
|
||||||
|
uint32_t lastDecommittedArenaOffset;
|
||||||
|
|
||||||
|
/* Number of free arenas, either committed or decommitted. */
|
||||||
|
uint32_t numArenasFree;
|
||||||
|
|
||||||
|
/* Number of free, committed arenas. */
|
||||||
|
uint32_t numArenasFreeCommitted;
|
||||||
|
|
||||||
|
/* Number of GC cycles this chunk has survived. */
|
||||||
|
uint32_t age;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Calculating ArenasPerChunk:
|
||||||
|
*
|
||||||
|
* In order to figure out how many Arenas will fit in a chunk, we need to know
|
||||||
|
* how much extra space is available after we allocate the header data. This
|
||||||
|
* is a problem because the header size depends on the number of arenas in the
|
||||||
|
* chunk. The two dependent fields are bitmap and decommittedArenas.
|
||||||
|
*
|
||||||
|
* For the mark bitmap, we know that each arena will use a fixed number of full
|
||||||
|
* bytes: ArenaBitmapBytes. The full size of the header data is this number
|
||||||
|
* multiplied by the eventual number of arenas we have in the header. We,
|
||||||
|
* conceptually, distribute this header data among the individual arenas and do
|
||||||
|
* not include it in the header. This way we do not have to worry about its
|
||||||
|
* variable size: it gets attached to the variable number we are computing.
|
||||||
|
*
|
||||||
|
* For the decommitted arena bitmap, we only have 1 bit per arena, so this
|
||||||
|
* technique will not work. Instead, we observe that we do not have enough
|
||||||
|
* header info to fill 8 full arenas: it is currently 4 on 64bit, less on
|
||||||
|
* 32bit. Thus, with current numbers, we need 64 bytes for decommittedArenas.
|
||||||
|
* This will not become 63 bytes unless we double the data required in the
|
||||||
|
* header. Therefore, we just compute the number of bytes required to track
|
||||||
|
* every possible arena and do not worry about slop bits, since there are too
|
||||||
|
* few to usefully allocate.
|
||||||
|
*
|
||||||
|
* To actually compute the number of arenas we can allocate in a chunk, we
|
||||||
|
* divide the amount of available space less the header info (not including
|
||||||
|
* the mark bitmap which is distributed into the arena size) by the size of
|
||||||
|
* the arena (with the mark bitmap bytes it uses).
|
||||||
|
*/
|
||||||
|
const size_t BytesPerArenaWithHeader = ArenaSize + ArenaBitmapBytes;
|
||||||
|
const size_t ChunkDecommitBitmapBytes = ChunkSize / ArenaSize / JS_BITS_PER_BYTE;
|
||||||
|
const size_t ChunkBytesAvailable = ChunkSize - sizeof(ChunkInfo) - ChunkDecommitBitmapBytes;
|
||||||
|
const size_t ArenasPerChunk = ChunkBytesAvailable / BytesPerArenaWithHeader;
|
||||||
|
|
||||||
|
/* A chunk bitmap contains enough mark bits for all the cells in a chunk. */
|
||||||
|
struct ChunkBitmap
|
||||||
|
{
|
||||||
|
uintptr_t bitmap[ArenaBitmapWords * ArenasPerChunk];
|
||||||
|
|
||||||
|
MOZ_ALWAYS_INLINE void getMarkWordAndMask(const Cell *cell, uint32_t color,
|
||||||
|
uintptr_t **wordp, uintptr_t *maskp);
|
||||||
|
|
||||||
|
MOZ_ALWAYS_INLINE bool isMarked(const Cell *cell, uint32_t color) {
|
||||||
|
uintptr_t *word, mask;
|
||||||
|
getMarkWordAndMask(cell, color, &word, &mask);
|
||||||
|
return *word & mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
MOZ_ALWAYS_INLINE bool markIfUnmarked(const Cell *cell, uint32_t color) {
|
||||||
|
uintptr_t *word, mask;
|
||||||
|
getMarkWordAndMask(cell, BLACK, &word, &mask);
|
||||||
|
if (*word & mask)
|
||||||
|
return false;
|
||||||
|
*word |= mask;
|
||||||
|
if (color != BLACK) {
|
||||||
|
/*
|
||||||
|
* We use getMarkWordAndMask to recalculate both mask and word as
|
||||||
|
* doing just mask << color may overflow the mask.
|
||||||
|
*/
|
||||||
|
getMarkWordAndMask(cell, color, &word, &mask);
|
||||||
|
if (*word & mask)
|
||||||
|
return false;
|
||||||
|
*word |= mask;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
MOZ_ALWAYS_INLINE void unmark(const Cell *cell, uint32_t color) {
|
||||||
|
uintptr_t *word, mask;
|
||||||
|
getMarkWordAndMask(cell, color, &word, &mask);
|
||||||
|
*word &= ~mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear() {
|
||||||
|
PodArrayZero(bitmap);
|
||||||
|
}
|
||||||
|
|
||||||
|
uintptr_t *arenaBits(ArenaHeader *aheader) {
|
||||||
|
/*
|
||||||
|
* We assume that the part of the bitmap corresponding to the arena
|
||||||
|
* has the exact number of words so we do not need to deal with a word
|
||||||
|
* that covers bits from two arenas.
|
||||||
|
*/
|
||||||
|
JS_STATIC_ASSERT(ArenaBitmapBits == ArenaBitmapWords * JS_BITS_PER_WORD);
|
||||||
|
|
||||||
|
uintptr_t *word, unused;
|
||||||
|
getMarkWordAndMask(reinterpret_cast<Cell *>(aheader->address()), BLACK, &word, &unused);
|
||||||
|
return word;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
JS_STATIC_ASSERT(ArenaBitmapBytes * ArenasPerChunk == sizeof(ChunkBitmap));
|
||||||
|
|
||||||
|
typedef BitArray<ArenasPerChunk> PerArenaBitmap;
|
||||||
|
|
||||||
|
const size_t ChunkPadSize = ChunkSize
|
||||||
|
- (sizeof(Arena) * ArenasPerChunk)
|
||||||
|
- sizeof(ChunkBitmap)
|
||||||
|
- sizeof(PerArenaBitmap)
|
||||||
|
- sizeof(ChunkInfo);
|
||||||
|
JS_STATIC_ASSERT(ChunkPadSize < BytesPerArenaWithHeader);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Chunks contain arenas and associated data structures (mark bitmap, delayed
|
||||||
|
* marking state).
|
||||||
|
*/
|
||||||
|
struct Chunk
|
||||||
|
{
|
||||||
|
Arena arenas[ArenasPerChunk];
|
||||||
|
|
||||||
|
/* Pad to full size to ensure cache alignment of ChunkInfo. */
|
||||||
|
uint8_t padding[ChunkPadSize];
|
||||||
|
|
||||||
|
ChunkBitmap bitmap;
|
||||||
|
PerArenaBitmap decommittedArenas;
|
||||||
|
ChunkInfo info;
|
||||||
|
|
||||||
|
static Chunk *fromAddress(uintptr_t addr) {
|
||||||
|
addr &= ~ChunkMask;
|
||||||
|
return reinterpret_cast<Chunk *>(addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool withinArenasRange(uintptr_t addr) {
|
||||||
|
uintptr_t offset = addr & ChunkMask;
|
||||||
|
return offset < ArenasPerChunk * ArenaSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t arenaIndex(uintptr_t addr) {
|
||||||
|
JS_ASSERT(withinArenasRange(addr));
|
||||||
|
return (addr & ChunkMask) >> ArenaShift;
|
||||||
|
}
|
||||||
|
|
||||||
|
uintptr_t address() const {
|
||||||
|
uintptr_t addr = reinterpret_cast<uintptr_t>(this);
|
||||||
|
JS_ASSERT(!(addr & ChunkMask));
|
||||||
|
return addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool unused() const {
|
||||||
|
return info.numArenasFree == ArenasPerChunk;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hasAvailableArenas() const {
|
||||||
|
return info.numArenasFree != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void addToAvailableList(JSCompartment *compartment);
|
||||||
|
inline void insertToAvailableList(Chunk **insertPoint);
|
||||||
|
inline void removeFromAvailableList();
|
||||||
|
|
||||||
|
ArenaHeader *allocateArena(JSCompartment *comp, AllocKind kind);
|
||||||
|
|
||||||
|
void releaseArena(ArenaHeader *aheader);
|
||||||
|
|
||||||
|
static Chunk *allocate(JSRuntime *rt);
|
||||||
|
|
||||||
|
/* Must be called with the GC lock taken. */
|
||||||
|
static inline void release(JSRuntime *rt, Chunk *chunk);
|
||||||
|
static inline void releaseList(JSRuntime *rt, Chunk *chunkListHead);
|
||||||
|
|
||||||
|
/* Must be called with the GC lock taken. */
|
||||||
|
inline void prepareToBeFreed(JSRuntime *rt);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Assuming that the info.prevp points to the next field of the previous
|
||||||
|
* chunk in a doubly-linked list, get that chunk.
|
||||||
|
*/
|
||||||
|
Chunk *getPrevious() {
|
||||||
|
JS_ASSERT(info.prevp);
|
||||||
|
return fromPointerToNext(info.prevp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the chunk from a pointer to its info.next field. */
|
||||||
|
static Chunk *fromPointerToNext(Chunk **nextFieldPtr) {
|
||||||
|
uintptr_t addr = reinterpret_cast<uintptr_t>(nextFieldPtr);
|
||||||
|
JS_ASSERT((addr & ChunkMask) == offsetof(Chunk, info.next));
|
||||||
|
return reinterpret_cast<Chunk *>(addr - offsetof(Chunk, info.next));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
inline void init();
|
||||||
|
|
||||||
|
/* Search for a decommitted arena to allocate. */
|
||||||
|
unsigned findDecommittedArenaOffset();
|
||||||
|
ArenaHeader* fetchNextDecommittedArena();
|
||||||
|
|
||||||
|
public:
|
||||||
|
/* Unlink and return the freeArenasHead. */
|
||||||
|
inline ArenaHeader* fetchNextFreeArena(JSRuntime *rt);
|
||||||
|
|
||||||
|
inline void addArenaToFreeList(JSRuntime *rt, ArenaHeader *aheader);
|
||||||
|
};
|
||||||
|
|
||||||
|
JS_STATIC_ASSERT(sizeof(Chunk) == ChunkSize);
|
||||||
|
|
||||||
|
inline uintptr_t
|
||||||
|
Cell::address() const
|
||||||
|
{
|
||||||
|
uintptr_t addr = uintptr_t(this);
|
||||||
|
JS_ASSERT(addr % Cell::CellSize == 0);
|
||||||
|
JS_ASSERT(Chunk::withinArenasRange(addr));
|
||||||
|
return addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uintptr_t
|
||||||
|
ArenaHeader::address() const
|
||||||
|
{
|
||||||
|
uintptr_t addr = reinterpret_cast<uintptr_t>(this);
|
||||||
|
JS_ASSERT(!(addr & ArenaMask));
|
||||||
|
JS_ASSERT(Chunk::withinArenasRange(addr));
|
||||||
|
return addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Chunk *
|
||||||
|
ArenaHeader::chunk() const
|
||||||
|
{
|
||||||
|
return Chunk::fromAddress(address());
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uintptr_t
|
||||||
|
ArenaHeader::arenaAddress() const
|
||||||
|
{
|
||||||
|
return address();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Arena *
|
||||||
|
ArenaHeader::getArena()
|
||||||
|
{
|
||||||
|
return reinterpret_cast<Arena *>(arenaAddress());
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool
|
||||||
|
ArenaHeader::isEmpty() const
|
||||||
|
{
|
||||||
|
/* Arena is empty if its first span covers the whole arena. */
|
||||||
|
JS_ASSERT(allocated());
|
||||||
|
size_t firstThingOffset = Arena::firstThingOffset(getAllocKind());
|
||||||
|
return firstFreeSpanOffsets == FreeSpan::encodeOffsets(firstThingOffset, ArenaMask);
|
||||||
|
}
|
||||||
|
|
||||||
|
FreeSpan
|
||||||
|
ArenaHeader::getFirstFreeSpan() const
|
||||||
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
checkSynchronizedWithFreeList();
|
||||||
|
#endif
|
||||||
|
return FreeSpan::decodeOffsets(arenaAddress(), firstFreeSpanOffsets);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ArenaHeader::setFirstFreeSpan(const FreeSpan *span)
|
||||||
|
{
|
||||||
|
JS_ASSERT(span->isWithinArena(arenaAddress()));
|
||||||
|
firstFreeSpanOffsets = span->encodeAsOffsets();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline ArenaHeader *
|
||||||
|
ArenaHeader::getNextDelayedMarking() const
|
||||||
|
{
|
||||||
|
return &reinterpret_cast<Arena *>(nextDelayedMarking << ArenaShift)->aheader;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void
|
||||||
|
ArenaHeader::setNextDelayedMarking(ArenaHeader *aheader)
|
||||||
|
{
|
||||||
|
JS_ASSERT(!(uintptr_t(aheader) & ArenaMask));
|
||||||
|
hasDelayedMarking = 1;
|
||||||
|
nextDelayedMarking = aheader->arenaAddress() >> ArenaShift;
|
||||||
|
}
|
||||||
|
|
||||||
|
JS_ALWAYS_INLINE void
|
||||||
|
ChunkBitmap::getMarkWordAndMask(const Cell *cell, uint32_t color,
|
||||||
|
uintptr_t **wordp, uintptr_t *maskp)
|
||||||
|
{
|
||||||
|
size_t bit = (cell->address() & ChunkMask) / Cell::CellSize + color;
|
||||||
|
JS_ASSERT(bit < ArenaBitmapBits * ArenasPerChunk);
|
||||||
|
*maskp = uintptr_t(1) << (bit % JS_BITS_PER_WORD);
|
||||||
|
*wordp = &bitmap[bit / JS_BITS_PER_WORD];
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
AssertValidColor(const void *thing, uint32_t color)
|
||||||
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
ArenaHeader *aheader = reinterpret_cast<const Cell *>(thing)->arenaHeader();
|
||||||
|
JS_ASSERT_IF(color, color < aheader->getThingSize() / Cell::CellSize);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
inline ArenaHeader *
|
||||||
|
Cell::arenaHeader() const
|
||||||
|
{
|
||||||
|
uintptr_t addr = address();
|
||||||
|
addr &= ~ArenaMask;
|
||||||
|
return reinterpret_cast<ArenaHeader *>(addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
Chunk *
|
||||||
|
Cell::chunk() const
|
||||||
|
{
|
||||||
|
uintptr_t addr = uintptr_t(this);
|
||||||
|
JS_ASSERT(addr % Cell::CellSize == 0);
|
||||||
|
addr &= ~(ChunkSize - 1);
|
||||||
|
return reinterpret_cast<Chunk *>(addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
AllocKind
|
||||||
|
Cell::getAllocKind() const
|
||||||
|
{
|
||||||
|
return arenaHeader()->getAllocKind();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
Cell::isMarked(uint32_t color /* = BLACK */) const
|
||||||
|
{
|
||||||
|
AssertValidColor(this, color);
|
||||||
|
return chunk()->bitmap.isMarked(this, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
Cell::markIfUnmarked(uint32_t color /* = BLACK */) const
|
||||||
|
{
|
||||||
|
AssertValidColor(this, color);
|
||||||
|
return chunk()->bitmap.markIfUnmarked(this, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Cell::unmark(uint32_t color) const
|
||||||
|
{
|
||||||
|
JS_ASSERT(color != BLACK);
|
||||||
|
AssertValidColor(this, color);
|
||||||
|
chunk()->bitmap.unmark(this, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
JSCompartment *
|
||||||
|
Cell::compartment() const
|
||||||
|
{
|
||||||
|
return arenaHeader()->compartment;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
bool
|
||||||
|
Cell::isAligned() const
|
||||||
|
{
|
||||||
|
return Arena::isAligned(address(), arenaHeader()->getThingSize());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} /* namespace gc */
|
||||||
|
|
||||||
|
} /* namespace js */
|
||||||
|
|
||||||
|
#endif /* gc_heap_h___ */
|
|
@ -1,51 +1,22 @@
|
||||||
/* -*- 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 -*-
|
||||||
* vim: set ts=8 sw=4 et tw=78:
|
* vim: set ts=8 sw=4 et tw=78:
|
||||||
*
|
*
|
||||||
* ***** BEGIN LICENSE BLOCK *****
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
* 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/. */
|
||||||
* 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__
|
#ifndef jsgc_root_h__
|
||||||
#define jsgc_root_h__
|
#define jsgc_root_h__
|
||||||
|
|
||||||
#include "jspubtd.h"
|
|
||||||
|
|
||||||
#include "js/Utility.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
||||||
|
#include "mozilla/TypeTraits.h"
|
||||||
|
|
||||||
|
#include "jsapi.h"
|
||||||
|
|
||||||
|
#include "js/TemplateLib.h"
|
||||||
|
#include "js/Utility.h"
|
||||||
|
|
||||||
namespace JS {
|
namespace JS {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -76,75 +47,159 @@ namespace JS {
|
||||||
* on the type T of the value being rooted, for which RootMethods<T> must
|
* on the type T of the value being rooted, for which RootMethods<T> must
|
||||||
* have an instantiation.
|
* have an instantiation.
|
||||||
*
|
*
|
||||||
* - Root<T> roots an existing stack allocated variable or other location of
|
* - Rooted<T> declares a variable of type T, whose value is always rooted.
|
||||||
* type T. This is typically used either when a variable only needs to be
|
* Rooted<T> may be automatically coerced to a Handle<T>, below. Rooted<T>
|
||||||
* rooted on certain rare paths, or when a function takes a bare GC thing
|
* should be used whenever a local variable's value may be held live across a
|
||||||
* pointer as an argument and needs to root it. In the latter case a
|
* call which can allocate GC things or otherwise trigger a GC.
|
||||||
* 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 Rooted<T>. Functions which take GC
|
||||||
*
|
* things or values as arguments and need to root those arguments should
|
||||||
* - Handle<T> is a const reference to a Root<T> or RootedVar<T>. Handles are
|
* generally use handles for those arguments and avoid any explicit rooting.
|
||||||
* coerced automatically from such a Root<T> or RootedVar<T>. Functions which
|
* This has two benefits. First, when several such functions call each other
|
||||||
* take GC things or values as arguments and need to root those arguments
|
* then redundant rooting of multiple copies of the GC thing can be avoided.
|
||||||
* should generally replace those arguments with handles and avoid any
|
* Second, if the caller does not pass a rooted value a compile error will be
|
||||||
* explicit rooting. This has two benefits. First, when several such
|
* generated, which is quicker and easier to fix than when relying on a
|
||||||
* functions call each other then redundant rooting of multiple copies of the
|
* separate rooting analysis.
|
||||||
* 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 Rooted;
|
||||||
template <typename T> class RootedVar;
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct RootMethods { };
|
struct RootMethods { };
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Reference to a stack location rooted for GC. See the "Moving GC Stack
|
* Handle provides an implicit constructor for NullPtr so that, given:
|
||||||
* Rooting" comment above.
|
* foo(Handle<JSObject*> h);
|
||||||
|
* callers can simply write:
|
||||||
|
* foo(NullPtr());
|
||||||
|
* which avoids creating a Rooted<JSObject*> just to pass NULL.
|
||||||
|
*/
|
||||||
|
struct NullPtr
|
||||||
|
{
|
||||||
|
static void * const constNullValue;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class HandleBase {};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reference to a T that has been rooted elsewhere. This is most useful
|
||||||
|
* as a parameter type, which guarantees that the T lvalue is properly
|
||||||
|
* rooted. See "Move GC Stack Rooting" above.
|
||||||
|
*
|
||||||
|
* If you want to add additional methods to Handle for a specific
|
||||||
|
* specialization, define a HandleBase<T> specialization containing them.
|
||||||
*/
|
*/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class Handle
|
class Handle : public HandleBase<T>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/* Copy handles of different types, with implicit coercion. */
|
/* Creates a handle from a handle of a type convertible to T. */
|
||||||
template <typename S> Handle(Handle<S> handle) {
|
template <typename S>
|
||||||
testAssign<S>();
|
Handle(Handle<S> handle,
|
||||||
|
typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type dummy = 0)
|
||||||
|
{
|
||||||
ptr = reinterpret_cast<const T *>(handle.address());
|
ptr = reinterpret_cast<const T *>(handle.address());
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get a handle from a rooted stack location, with implicit coercion. */
|
/* Create a handle for a NULL pointer. */
|
||||||
template <typename S> inline Handle(const Root<S> &root);
|
Handle(NullPtr) {
|
||||||
template <typename S> inline Handle(const RootedVar<S> &root);
|
typedef typename js::tl::StaticAssert<js::tl::IsPointerType<T>::result>::result _;
|
||||||
|
ptr = reinterpret_cast<const T *>(&NullPtr::constNullValue);
|
||||||
|
}
|
||||||
|
|
||||||
const T *address() { return ptr; }
|
/*
|
||||||
|
* This may be called only if the location of the T is guaranteed
|
||||||
|
* to be marked (for some reason other than being a Rooted),
|
||||||
|
* e.g., if it is guaranteed to be reachable from an implicit root.
|
||||||
|
*
|
||||||
|
* Create a Handle from a raw location of a T.
|
||||||
|
*/
|
||||||
|
static Handle fromMarkedLocation(const T *p) {
|
||||||
|
Handle h;
|
||||||
|
h.ptr = p;
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
operator T () { return value(); }
|
/*
|
||||||
T operator ->() { return value(); }
|
* Construct a handle from an explicitly rooted location. This is the
|
||||||
|
* normal way to create a handle, and normally happens implicitly.
|
||||||
|
*/
|
||||||
|
template <typename S>
|
||||||
|
inline
|
||||||
|
Handle(Rooted<S> &root,
|
||||||
|
typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type dummy = 0);
|
||||||
|
|
||||||
|
const T *address() const { return ptr; }
|
||||||
|
T get() const { return *ptr; }
|
||||||
|
|
||||||
|
operator T () const { return get(); }
|
||||||
|
T operator ->() const { return get(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Handle() {}
|
||||||
|
|
||||||
const T *ptr;
|
const T *ptr;
|
||||||
T value() { return *ptr; }
|
|
||||||
|
|
||||||
template <typename S>
|
template <typename S>
|
||||||
void testAssign() {
|
void operator =(S v) MOZ_DELETE;
|
||||||
#ifdef DEBUG
|
|
||||||
T a = RootMethods<T>::initial();
|
|
||||||
S b = RootMethods<S>::initial();
|
|
||||||
a = b;
|
|
||||||
(void)a;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef Handle<JSObject*> HandleObject;
|
typedef Handle<JSObject*> HandleObject;
|
||||||
typedef Handle<JSFunction*> HandleFunction;
|
typedef Handle<JSFunction*> HandleFunction;
|
||||||
|
typedef Handle<JSScript*> HandleScript;
|
||||||
typedef Handle<JSString*> HandleString;
|
typedef Handle<JSString*> HandleString;
|
||||||
typedef Handle<jsid> HandleId;
|
typedef Handle<jsid> HandleId;
|
||||||
typedef Handle<Value> HandleValue;
|
typedef Handle<Value> HandleValue;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class MutableHandleBase {};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Similar to a handle, but the underlying storage can be changed. This is
|
||||||
|
* useful for outparams.
|
||||||
|
*
|
||||||
|
* If you want to add additional methods to MutableHandle for a specific
|
||||||
|
* specialization, define a MutableHandleBase<T> specialization containing
|
||||||
|
* them.
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
class MutableHandle : public MutableHandleBase<T>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
template <typename S>
|
||||||
|
MutableHandle(MutableHandle<S> handle,
|
||||||
|
typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type dummy = 0)
|
||||||
|
{
|
||||||
|
this->ptr = reinterpret_cast<const T *>(handle.address());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename S>
|
||||||
|
inline
|
||||||
|
MutableHandle(Rooted<S> *root,
|
||||||
|
typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type dummy = 0);
|
||||||
|
|
||||||
|
void set(T v)
|
||||||
|
{
|
||||||
|
JS_ASSERT(!RootMethods<T>::poisoned(v));
|
||||||
|
*ptr = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
T *address() const { return ptr; }
|
||||||
|
T get() const { return *ptr; }
|
||||||
|
|
||||||
|
operator T () const { return get(); }
|
||||||
|
T operator ->() const { return get(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
MutableHandle() {}
|
||||||
|
|
||||||
|
T *ptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef MutableHandle<JSObject*> MutableHandleObject;
|
||||||
|
typedef MutableHandle<Value> MutableHandleValue;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct RootMethods<T *>
|
struct RootMethods<T *>
|
||||||
{
|
{
|
||||||
|
@ -153,76 +208,103 @@ struct RootMethods<T *>
|
||||||
static bool poisoned(T *v) { return IsPoisonedPtr(v); }
|
static bool poisoned(T *v) { return IsPoisonedPtr(v); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class RootedBase {};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Root a stack location holding a GC thing. This takes a stack pointer
|
* Local variable of type T whose value is always rooted. This is typically
|
||||||
* and ensures that throughout its lifetime the referenced variable
|
* used for local variables, or for non-rooted values being passed to a
|
||||||
* will remain pinned against a moving GC.
|
* function that requires a handle, e.g. Foo(Root<T>(cx, x)).
|
||||||
*
|
*
|
||||||
* It is important to ensure that the location referenced by a Root is
|
* If you want to add additional methods to Rooted for a specific
|
||||||
* initialized, as otherwise the GC may try to use the the uninitialized value.
|
* specialization, define a RootedBase<T> specialization containing them.
|
||||||
* It is generally preferable to use either RootedVar for local variables, or
|
|
||||||
* Handle for arguments.
|
|
||||||
*/
|
*/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class Root
|
class Rooted : public RootedBase<T>
|
||||||
{
|
{
|
||||||
public:
|
void init(JSContext *cx_)
|
||||||
Root(JSContext *cx_, const T *ptr
|
|
||||||
JS_GUARD_OBJECT_NOTIFIER_PARAM)
|
|
||||||
{
|
{
|
||||||
#ifdef JSGC_ROOT_ANALYSIS
|
#if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)
|
||||||
ContextFriendFields *cx = ContextFriendFields::get(cx_);
|
ContextFriendFields *cx = ContextFriendFields::get(cx_);
|
||||||
|
|
||||||
ThingRootKind kind = RootMethods<T>::kind();
|
ThingRootKind kind = RootMethods<T>::kind();
|
||||||
this->stack = reinterpret_cast<Root<T>**>(&cx->thingGCRooters[kind]);
|
this->stack = reinterpret_cast<Rooted<T>**>(&cx->thingGCRooters[kind]);
|
||||||
this->prev = *stack;
|
this->prev = *stack;
|
||||||
*stack = this;
|
*stack = this;
|
||||||
|
|
||||||
|
JS_ASSERT(!RootMethods<T>::poisoned(ptr));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
JS_ASSERT(!RootMethods<T>::poisoned(*ptr));
|
|
||||||
|
|
||||||
this->ptr = ptr;
|
|
||||||
|
|
||||||
JS_GUARD_OBJECT_NOTIFIER_INIT;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
~Root()
|
public:
|
||||||
|
Rooted(JSContext *cx) : ptr(RootMethods<T>::initial()) { init(cx); }
|
||||||
|
Rooted(JSContext *cx, T initial) : ptr(initial) { init(cx); }
|
||||||
|
|
||||||
|
~Rooted()
|
||||||
{
|
{
|
||||||
#ifdef JSGC_ROOT_ANALYSIS
|
#if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)
|
||||||
JS_ASSERT(*stack == this);
|
JS_ASSERT(*stack == this);
|
||||||
*stack = prev;
|
*stack = prev;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef JSGC_ROOT_ANALYSIS
|
#if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)
|
||||||
Root<T> *previous() { return prev; }
|
Rooted<T> *previous() { return prev; }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const T *address() const { return ptr; }
|
operator T () const { return ptr; }
|
||||||
|
T operator ->() const { return ptr; }
|
||||||
|
T * address() { return &ptr; }
|
||||||
|
const T * address() const { return &ptr; }
|
||||||
|
T & get() { return ptr; }
|
||||||
|
const T & get() const { return ptr; }
|
||||||
|
|
||||||
|
T & operator =(T value)
|
||||||
|
{
|
||||||
|
JS_ASSERT(!RootMethods<T>::poisoned(value));
|
||||||
|
ptr = value;
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
T & operator =(const Rooted &value)
|
||||||
|
{
|
||||||
|
ptr = value;
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
#ifdef JSGC_ROOT_ANALYSIS
|
#if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)
|
||||||
Root<T> **stack, *prev;
|
Rooted<T> **stack, *prev;
|
||||||
#endif
|
#endif
|
||||||
const T *ptr;
|
T ptr;
|
||||||
|
|
||||||
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
|
Rooted() MOZ_DELETE;
|
||||||
|
Rooted(const Rooted &) MOZ_DELETE;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T> template <typename S>
|
template<typename T> template <typename S>
|
||||||
inline
|
inline
|
||||||
Handle<T>::Handle(const Root<S> &root)
|
Handle<T>::Handle(Rooted<S> &root,
|
||||||
|
typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type dummy)
|
||||||
{
|
{
|
||||||
testAssign<S>();
|
|
||||||
ptr = reinterpret_cast<const T *>(root.address());
|
ptr = reinterpret_cast<const T *>(root.address());
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef Root<JSObject*> RootObject;
|
template<typename T> template <typename S>
|
||||||
typedef Root<JSFunction*> RootFunction;
|
inline
|
||||||
typedef Root<JSString*> RootString;
|
MutableHandle<T>::MutableHandle(Rooted<S> *root,
|
||||||
typedef Root<jsid> RootId;
|
typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type dummy)
|
||||||
typedef Root<Value> RootValue;
|
{
|
||||||
|
ptr = root->address();
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef Rooted<JSObject*> RootedObject;
|
||||||
|
typedef Rooted<JSFunction*> RootedFunction;
|
||||||
|
typedef Rooted<JSScript*> RootedScript;
|
||||||
|
typedef Rooted<JSString*> RootedString;
|
||||||
|
typedef Rooted<jsid> RootedId;
|
||||||
|
typedef Rooted<Value> RootedValue;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Mark a stack location as a root for the rooting analysis, without actually
|
* Mark a stack location as a root for the rooting analysis, without actually
|
||||||
|
@ -238,18 +320,30 @@ class SkipRoot
|
||||||
const uint8_t *start;
|
const uint8_t *start;
|
||||||
const uint8_t *end;
|
const uint8_t *end;
|
||||||
|
|
||||||
public:
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
SkipRoot(JSContext *cx_, const T *ptr
|
void init(ContextFriendFields *cx, const T *ptr, size_t count)
|
||||||
JS_GUARD_OBJECT_NOTIFIER_PARAM)
|
|
||||||
{
|
{
|
||||||
ContextFriendFields *cx = ContextFriendFields::get(cx_);
|
|
||||||
|
|
||||||
this->stack = &cx->skipGCRooters;
|
this->stack = &cx->skipGCRooters;
|
||||||
this->prev = *stack;
|
this->prev = *stack;
|
||||||
*stack = this;
|
*stack = this;
|
||||||
this->start = (const uint8_t *) ptr;
|
this->start = (const uint8_t *) ptr;
|
||||||
this->end = this->start + sizeof(T);
|
this->end = this->start + (sizeof(T) * count);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
template <typename T>
|
||||||
|
SkipRoot(JSContext *cx, const T *ptr
|
||||||
|
JS_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||||
|
{
|
||||||
|
init(ContextFriendFields::get(cx), ptr, 1);
|
||||||
|
JS_GUARD_OBJECT_NOTIFIER_INIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
SkipRoot(JSContext *cx, const T *ptr, size_t count
|
||||||
|
JS_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||||
|
{
|
||||||
|
init(ContextFriendFields::get(cx), ptr, count);
|
||||||
JS_GUARD_OBJECT_NOTIFIER_INIT;
|
JS_GUARD_OBJECT_NOTIFIER_INIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -275,74 +369,66 @@ class SkipRoot
|
||||||
JS_GUARD_OBJECT_NOTIFIER_INIT;
|
JS_GUARD_OBJECT_NOTIFIER_INIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
SkipRoot(JSContext *cx, const T *ptr, size_t count
|
||||||
|
JS_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||||
|
{
|
||||||
|
JS_GUARD_OBJECT_NOTIFIER_INIT;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* DEBUG && JSGC_ROOT_ANALYSIS */
|
#endif /* DEBUG && JSGC_ROOT_ANALYSIS */
|
||||||
|
|
||||||
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
|
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Make a local variable which stays rooted throughout its lifetime. */
|
#ifdef DEBUG
|
||||||
template <typename T>
|
JS_FRIEND_API(bool) IsRootingUnnecessaryForContext(JSContext *cx);
|
||||||
class RootedVar
|
JS_FRIEND_API(void) SetRootingUnnecessaryForContext(JSContext *cx, bool value);
|
||||||
{
|
JS_FRIEND_API(bool) RelaxRootChecksForContext(JSContext *cx);
|
||||||
public:
|
#endif
|
||||||
RootedVar(JSContext *cx)
|
|
||||||
: ptr(RootMethods<T>::initial()), root(cx, &ptr)
|
|
||||||
{}
|
|
||||||
|
|
||||||
RootedVar(JSContext *cx, T initial)
|
class AssertRootingUnnecessary {
|
||||||
: ptr(initial), root(cx, &ptr)
|
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||||
{}
|
JSContext *cx;
|
||||||
|
bool prev;
|
||||||
operator T () const { return ptr; }
|
public:
|
||||||
T operator ->() const { return ptr; }
|
AssertRootingUnnecessary(JSContext *cx JS_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||||
T * address() { return &ptr; }
|
: cx(cx)
|
||||||
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));
|
JS_GUARD_OBJECT_NOTIFIER_INIT;
|
||||||
ptr = value;
|
#ifdef DEBUG
|
||||||
return ptr;
|
prev = IsRootingUnnecessaryForContext(cx);
|
||||||
|
SetRootingUnnecessaryForContext(cx, true);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
T & operator =(const RootedVar &value)
|
~AssertRootingUnnecessary() {
|
||||||
{
|
#ifdef DEBUG
|
||||||
ptr = value;
|
SetRootingUnnecessaryForContext(cx, prev);
|
||||||
return ptr;
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
|
||||||
T ptr;
|
|
||||||
Root<T> root;
|
|
||||||
|
|
||||||
RootedVar() MOZ_DELETE;
|
|
||||||
RootedVar(const RootedVar &) MOZ_DELETE;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T> template <typename S>
|
#if defined(DEBUG) && defined(JS_GC_ZEAL) && defined(JSGC_ROOT_ANALYSIS) && !defined(JS_THREADSAFE)
|
||||||
inline
|
extern void
|
||||||
Handle<T>::Handle(const RootedVar<S> &root)
|
CheckStackRoots(JSContext *cx);
|
||||||
{
|
#endif
|
||||||
testAssign<S>();
|
|
||||||
ptr = reinterpret_cast<const T *>(root.address());
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef RootedVar<JSObject*> RootedVarObject;
|
/*
|
||||||
typedef RootedVar<JSFunction*> RootedVarFunction;
|
* Hook for dynamic root analysis. Checks the native stack and poisons
|
||||||
typedef RootedVar<JSString*> RootedVarString;
|
* references to GC things which have not been rooted.
|
||||||
typedef RootedVar<jsid> RootedVarId;
|
*/
|
||||||
typedef RootedVar<Value> RootedVarValue;
|
inline void MaybeCheckStackRoots(JSContext *cx, bool relax = true)
|
||||||
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
JS_ASSERT(!IsRootingUnnecessaryForContext(cx));
|
||||||
|
# if defined(JS_GC_ZEAL) && defined(JSGC_ROOT_ANALYSIS) && !defined(JS_THREADSAFE)
|
||||||
|
if (relax && RelaxRootChecksForContext(cx))
|
||||||
|
return;
|
||||||
|
CheckStackRoots(cx);
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
} /* namespace JS */
|
} /* namespace JS */
|
||||||
|
|
||||||
|
|
|
@ -1,41 +1,9 @@
|
||||||
/* -*- 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 -*-
|
||||||
* vim: set ts=8 sw=4 et tw=78:
|
* vim: set ts=8 sw=4 et tw=78:
|
||||||
*
|
*
|
||||||
* ***** BEGIN LICENSE BLOCK *****
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
* 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/. */
|
||||||
* 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___
|
#ifndef jsgc_statistics_h___
|
||||||
#define jsgc_statistics_h___
|
#define jsgc_statistics_h___
|
||||||
|
@ -56,19 +24,26 @@ enum Phase {
|
||||||
PHASE_WAIT_BACKGROUND_THREAD,
|
PHASE_WAIT_BACKGROUND_THREAD,
|
||||||
PHASE_PURGE,
|
PHASE_PURGE,
|
||||||
PHASE_MARK,
|
PHASE_MARK,
|
||||||
|
PHASE_MARK_DISCARD_CODE,
|
||||||
PHASE_MARK_ROOTS,
|
PHASE_MARK_ROOTS,
|
||||||
|
PHASE_MARK_TYPES,
|
||||||
PHASE_MARK_DELAYED,
|
PHASE_MARK_DELAYED,
|
||||||
PHASE_MARK_OTHER,
|
PHASE_MARK_WEAK,
|
||||||
|
PHASE_MARK_GRAY,
|
||||||
|
PHASE_MARK_GRAY_WEAK,
|
||||||
PHASE_FINALIZE_START,
|
PHASE_FINALIZE_START,
|
||||||
PHASE_SWEEP,
|
PHASE_SWEEP,
|
||||||
|
PHASE_SWEEP_ATOMS,
|
||||||
PHASE_SWEEP_COMPARTMENTS,
|
PHASE_SWEEP_COMPARTMENTS,
|
||||||
|
PHASE_SWEEP_TABLES,
|
||||||
PHASE_SWEEP_OBJECT,
|
PHASE_SWEEP_OBJECT,
|
||||||
PHASE_SWEEP_STRING,
|
PHASE_SWEEP_STRING,
|
||||||
PHASE_SWEEP_SCRIPT,
|
PHASE_SWEEP_SCRIPT,
|
||||||
PHASE_SWEEP_SHAPE,
|
PHASE_SWEEP_SHAPE,
|
||||||
PHASE_DISCARD_CODE,
|
PHASE_SWEEP_DISCARD_CODE,
|
||||||
PHASE_DISCARD_ANALYSIS,
|
PHASE_DISCARD_ANALYSIS,
|
||||||
PHASE_DISCARD_TI,
|
PHASE_DISCARD_TI,
|
||||||
|
PHASE_FREE_TI_ARENA,
|
||||||
PHASE_SWEEP_TYPES,
|
PHASE_SWEEP_TYPES,
|
||||||
PHASE_CLEAR_SCRIPT_ANALYSIS,
|
PHASE_CLEAR_SCRIPT_ANALYSIS,
|
||||||
PHASE_FINALIZE_END,
|
PHASE_FINALIZE_END,
|
||||||
|
@ -116,13 +91,19 @@ struct Statistics {
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
bool fullFormat;
|
bool fullFormat;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GCs can't really nest, but a second GC can be triggered from within the
|
||||||
|
* JSGC_END callback.
|
||||||
|
*/
|
||||||
|
int gcDepth;
|
||||||
|
|
||||||
int collectedCount;
|
int collectedCount;
|
||||||
int compartmentCount;
|
int compartmentCount;
|
||||||
const char *nonincrementalReason;
|
const char *nonincrementalReason;
|
||||||
|
|
||||||
struct SliceData {
|
struct SliceData {
|
||||||
SliceData(gcreason::Reason reason, int64_t start)
|
SliceData(gcreason::Reason reason, int64_t start, size_t startFaults)
|
||||||
: reason(reason), resetReason(NULL), start(start)
|
: reason(reason), resetReason(NULL), start(start), startFaults(startFaults)
|
||||||
{
|
{
|
||||||
PodArrayZero(phaseTimes);
|
PodArrayZero(phaseTimes);
|
||||||
}
|
}
|
||||||
|
@ -130,6 +111,7 @@ struct Statistics {
|
||||||
gcreason::Reason reason;
|
gcreason::Reason reason;
|
||||||
const char *resetReason;
|
const char *resetReason;
|
||||||
int64_t start, end;
|
int64_t start, end;
|
||||||
|
size_t startFaults, endFaults;
|
||||||
int64_t phaseTimes[PHASE_LIMIT];
|
int64_t phaseTimes[PHASE_LIMIT];
|
||||||
|
|
||||||
int64_t duration() const { return end - start; }
|
int64_t duration() const { return end - start; }
|
||||||
|
@ -138,7 +120,7 @@ struct Statistics {
|
||||||
Vector<SliceData, 8, SystemAllocPolicy> slices;
|
Vector<SliceData, 8, SystemAllocPolicy> slices;
|
||||||
|
|
||||||
/* Most recent time when the given phase started. */
|
/* Most recent time when the given phase started. */
|
||||||
int64_t phaseStarts[PHASE_LIMIT];
|
int64_t phaseStartTimes[PHASE_LIMIT];
|
||||||
|
|
||||||
/* Total time in a given phase for this GC. */
|
/* Total time in a given phase for this GC. */
|
||||||
int64_t phaseTimes[PHASE_LIMIT];
|
int64_t phaseTimes[PHASE_LIMIT];
|
||||||
|
|
|
@ -2,42 +2,9 @@
|
||||||
/* -*- 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 -*-
|
||||||
* vim: set ts=8 sw=4 et tw=78:
|
* vim: set ts=8 sw=4 et tw=78:
|
||||||
*
|
*
|
||||||
* ***** BEGIN LICENSE BLOCK *****
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
* 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/. */
|
||||||
* 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 js_config_h___
|
#ifndef js_config_h___
|
||||||
#define js_config_h___
|
#define js_config_h___
|
||||||
|
@ -54,7 +21,7 @@
|
||||||
|
|
||||||
/* Define to 1 if SpiderMonkey should support the ability to perform
|
/* Define to 1 if SpiderMonkey should support the ability to perform
|
||||||
entirely too much GC. */
|
entirely too much GC. */
|
||||||
/* #undef JS_GC_ZEAL */
|
#define JS_GC_ZEAL 1
|
||||||
|
|
||||||
/* Define to 1 if the <endian.h> header is present and
|
/* Define to 1 if the <endian.h> header is present and
|
||||||
useable. See jscpucfg.h. */
|
useable. See jscpucfg.h. */
|
||||||
|
@ -96,4 +63,7 @@
|
||||||
correct. */
|
correct. */
|
||||||
/* #undef JS_METHODJIT */
|
/* #undef JS_METHODJIT */
|
||||||
|
|
||||||
|
/* Define to 1 to enable support for E4X (ECMA-357), 0 to disable it. */
|
||||||
|
#define JS_HAS_XML_SUPPORT 1
|
||||||
|
|
||||||
#endif /* js_config_h___ */
|
#endif /* js_config_h___ */
|
||||||
|
|
|
@ -1,41 +1,8 @@
|
||||||
/* -*- 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 *****
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
* 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/. */
|
||||||
* 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.
|
* This is the JavaScript error message file.
|
||||||
|
@ -147,8 +114,8 @@ 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_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_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_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_ARG_INDEX_OUT_OF_RANGE, 64, 1, JSEXN_RANGEERR, "argument {0} accesses an index that is out of range")
|
||||||
MSG_DEF(JSMSG_UNUSED65, 65, 0, JSEXN_NONE, "")
|
MSG_DEF(JSMSG_SPREAD_TOO_LARGE, 65, 0, JSEXN_RANGEERR, "array too large due to spread operand(s)")
|
||||||
MSG_DEF(JSMSG_UNUSED66, 66, 0, JSEXN_NONE, "")
|
MSG_DEF(JSMSG_UNUSED66, 66, 0, JSEXN_NONE, "")
|
||||||
MSG_DEF(JSMSG_UNUSED67, 67, 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_BAD_SCRIPT_MAGIC, 68, 0, JSEXN_INTERNALERR, "bad script XDR magic number")
|
||||||
|
@ -258,7 +225,7 @@ MSG_DEF(JSMSG_BAD_XML_CHARACTER, 171, 0, JSEXN_SYNTAXERR, "illegal XML char
|
||||||
MSG_DEF(JSMSG_BAD_DEFAULT_XML_NAMESPACE,172,0,JSEXN_SYNTAXERR, "invalid default XML namespace")
|
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_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_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_NESTING_GENERATOR, 175, 0, JSEXN_TYPEERR, "already executing generator")
|
||||||
MSG_DEF(JSMSG_CURLY_IN_XML_EXPR, 176, 0, JSEXN_SYNTAXERR, "missing } in XML expression")
|
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_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_ATTR_NAME, 178, 1, JSEXN_TYPEERR, "invalid XML attribute name {0}")
|
||||||
|
@ -378,4 +345,10 @@ MSG_DEF(JSMSG_NOT_ITERABLE, 291, 1, JSEXN_TYPEERR, "{0} is not iterabl
|
||||||
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_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_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")
|
MSG_DEF(JSMSG_DEBUG_VARIABLE_NOT_FOUND, 294, 0, JSEXN_TYPEERR, "variable not found in environment")
|
||||||
|
MSG_DEF(JSMSG_PARAMETER_AFTER_REST, 295, 0, JSEXN_SYNTAXERR, "parameter after rest parameter")
|
||||||
|
MSG_DEF(JSMSG_NO_REST_NAME, 296, 0, JSEXN_SYNTAXERR, "no parameter name after ...")
|
||||||
|
MSG_DEF(JSMSG_ARGUMENTS_AND_REST, 297, 0, JSEXN_SYNTAXERR, "'arguments' object may not be used in conjunction with a rest parameter")
|
||||||
|
MSG_DEF(JSMSG_FUNCTION_ARGUMENTS_AND_REST, 298, 0, JSEXN_ERR, "the 'arguments' property of a function with a rest parameter may not be used")
|
||||||
|
MSG_DEF(JSMSG_REST_WITH_DEFAULT, 299, 0, JSEXN_SYNTAXERR, "rest parameter may not have a default")
|
||||||
|
MSG_DEF(JSMSG_NONDEFAULT_FORMAL_AFTER_DEFAULT, 300, 0, JSEXN_SYNTAXERR, "parameter(s) with default followed by parameter without default")
|
||||||
|
MSG_DEF(JSMSG_YIELD_IN_DEFAULT, 301, 0, JSEXN_SYNTAXERR, "yield in default expression")
|
||||||
|
|
|
@ -1,44 +1,9 @@
|
||||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||||
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
|
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
|
||||||
*
|
*
|
||||||
* ***** BEGIN LICENSE BLOCK *****
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
* 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/. */
|
||||||
* 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
|
|
||||||
* November 13, 2009.
|
|
||||||
*
|
|
||||||
* The Initial Developer of the Original Code is
|
|
||||||
* the Mozilla Corporation.
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* Brendan Eich <brendan@mozilla.org> (Original Author)
|
|
||||||
* Chris Waterson <waterson@netscape.com>
|
|
||||||
* L. David Baron <dbaron@dbaron.org>, Mozilla Corporation
|
|
||||||
* Luke Wagner <lw@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 jshashtable_h_
|
#ifndef jshashtable_h_
|
||||||
#define jshashtable_h_
|
#define jshashtable_h_
|
||||||
|
@ -97,7 +62,7 @@ class HashTableEntry {
|
||||||
JS_ASSERT(isLive()); keyHash |= collisionBit;
|
JS_ASSERT(isLive()); keyHash |= collisionBit;
|
||||||
}
|
}
|
||||||
void unsetCollision() { keyHash &= ~sCollisionBit; }
|
void unsetCollision() { keyHash &= ~sCollisionBit; }
|
||||||
bool hasCollision() const { JS_ASSERT(isLive()); return keyHash & sCollisionBit; }
|
bool hasCollision() const { return keyHash & sCollisionBit; }
|
||||||
bool matchHash(HashNumber hn) { return (keyHash & ~sCollisionBit) == hn; }
|
bool matchHash(HashNumber hn) { return (keyHash & ~sCollisionBit) == hn; }
|
||||||
HashNumber getKeyHash() const { JS_ASSERT(!hasCollision()); return keyHash; }
|
HashNumber getKeyHash() const { JS_ASSERT(!hasCollision()); return keyHash; }
|
||||||
};
|
};
|
||||||
|
@ -177,21 +142,23 @@ class HashTable : private AllocPolicy
|
||||||
protected:
|
protected:
|
||||||
friend class HashTable;
|
friend class HashTable;
|
||||||
|
|
||||||
Range(Entry *c, Entry *e) : cur(c), end(e) {
|
Range(Entry *c, Entry *e) : cur(c), end(e), validEntry(true) {
|
||||||
while (cur < end && !cur->isLive())
|
while (cur < end && !cur->isLive())
|
||||||
++cur;
|
++cur;
|
||||||
}
|
}
|
||||||
|
|
||||||
Entry *cur, *end;
|
Entry *cur, *end;
|
||||||
|
DebugOnly<bool> validEntry;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Range() : cur(NULL), end(NULL) {}
|
Range() : cur(NULL), end(NULL), validEntry(false) {}
|
||||||
|
|
||||||
bool empty() const {
|
bool empty() const {
|
||||||
return cur == end;
|
return cur == end;
|
||||||
}
|
}
|
||||||
|
|
||||||
T &front() const {
|
T &front() const {
|
||||||
|
JS_ASSERT(validEntry);
|
||||||
JS_ASSERT(!empty());
|
JS_ASSERT(!empty());
|
||||||
return cur->t;
|
return cur->t;
|
||||||
}
|
}
|
||||||
|
@ -200,6 +167,7 @@ class HashTable : private AllocPolicy
|
||||||
JS_ASSERT(!empty());
|
JS_ASSERT(!empty());
|
||||||
while (++cur < end && !cur->isLive())
|
while (++cur < end && !cur->isLive())
|
||||||
continue;
|
continue;
|
||||||
|
validEntry = true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -217,7 +185,7 @@ class HashTable : private AllocPolicy
|
||||||
friend class HashTable;
|
friend class HashTable;
|
||||||
|
|
||||||
HashTable &table;
|
HashTable &table;
|
||||||
bool added;
|
bool rekeyed;
|
||||||
bool removed;
|
bool removed;
|
||||||
|
|
||||||
/* Not copyable. */
|
/* Not copyable. */
|
||||||
|
@ -226,7 +194,7 @@ class HashTable : private AllocPolicy
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template<class Map> explicit
|
template<class Map> explicit
|
||||||
Enum(Map &map) : Range(map.all()), table(map.impl), added(false), removed(false) {}
|
Enum(Map &map) : Range(map.all()), table(map.impl), rekeyed(false), removed(false) {}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Removes the |front()| element from the table, leaving |front()|
|
* Removes the |front()| element from the table, leaving |front()|
|
||||||
|
@ -240,6 +208,7 @@ class HashTable : private AllocPolicy
|
||||||
void removeFront() {
|
void removeFront() {
|
||||||
table.remove(*this->cur);
|
table.remove(*this->cur);
|
||||||
removed = true;
|
removed = true;
|
||||||
|
this->validEntry = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -247,35 +216,29 @@ class HashTable : private AllocPolicy
|
||||||
* a new key at the new Lookup position. |front()| is invalid after
|
* a new key at the new Lookup position. |front()| is invalid after
|
||||||
* this operation until the next call to |popFront()|.
|
* this operation until the next call to |popFront()|.
|
||||||
*/
|
*/
|
||||||
void rekeyFront(Key &k) {
|
void rekeyFront(const Lookup &l, const Key &k) {
|
||||||
JS_ASSERT(&k != &HashPolicy::getKey(this->cur->t));
|
JS_ASSERT(&k != &HashPolicy::getKey(this->cur->t));
|
||||||
JS_ASSERT(!table.match(*this->cur, k));
|
if (match(*this->cur, l))
|
||||||
Entry e = *this->cur;
|
return;
|
||||||
HashPolicy::setKey(e.t, k);
|
typename HashTableEntry<T>::NonConstT t = this->cur->t;
|
||||||
|
HashPolicy::setKey(t, const_cast<Key &>(k));
|
||||||
table.remove(*this->cur);
|
table.remove(*this->cur);
|
||||||
table.add(k, e);
|
table.putNewInfallible(l, t);
|
||||||
added = true;
|
rekeyed = true;
|
||||||
|
this->validEntry = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rekeyFront(const Key &k) {
|
||||||
|
rekeyFront(k, k);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Potentially rehashes the table. */
|
/* Potentially rehashes the table. */
|
||||||
~Enum() {
|
~Enum() {
|
||||||
if (added)
|
if (rekeyed)
|
||||||
table.checkOverloaded();
|
table.checkOverRemoved();
|
||||||
if (removed)
|
if (removed)
|
||||||
table.checkUnderloaded();
|
table.checkUnderloaded();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Can be used to end the enumeration before the destructor. */
|
|
||||||
void endEnumeration() {
|
|
||||||
if (added) {
|
|
||||||
table.checkOverloaded();
|
|
||||||
added = false;
|
|
||||||
}
|
|
||||||
if (removed) {
|
|
||||||
table.checkUnderloaded();
|
|
||||||
removed = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -301,6 +264,7 @@ class HashTable : private AllocPolicy
|
||||||
uint32_t grows; /* table expansions */
|
uint32_t grows; /* table expansions */
|
||||||
uint32_t shrinks; /* table contractions */
|
uint32_t shrinks; /* table contractions */
|
||||||
uint32_t compresses; /* table compressions */
|
uint32_t compresses; /* table compressions */
|
||||||
|
uint32_t rehashes; /* tombstone decontaminations */
|
||||||
} stats;
|
} stats;
|
||||||
# define METER(x) x
|
# define METER(x) x
|
||||||
#else
|
#else
|
||||||
|
@ -384,7 +348,7 @@ class HashTable : private AllocPolicy
|
||||||
mutationCount(0)
|
mutationCount(0)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
bool init(uint32_t length)
|
MOZ_WARN_UNUSED_RESULT bool init(uint32_t length)
|
||||||
{
|
{
|
||||||
/* Make sure that init isn't called twice. */
|
/* Make sure that init isn't called twice. */
|
||||||
JS_ASSERT(table == NULL);
|
JS_ASSERT(table == NULL);
|
||||||
|
@ -533,8 +497,9 @@ class HashTable : private AllocPolicy
|
||||||
*/
|
*/
|
||||||
Entry &findFreeEntry(HashNumber keyHash)
|
Entry &findFreeEntry(HashNumber keyHash)
|
||||||
{
|
{
|
||||||
METER(stats.searches++);
|
|
||||||
JS_ASSERT(!(keyHash & sCollisionBit));
|
JS_ASSERT(!(keyHash & sCollisionBit));
|
||||||
|
JS_ASSERT(table);
|
||||||
|
METER(stats.searches++);
|
||||||
|
|
||||||
/* N.B. the |keyHash| has already been distributed. */
|
/* N.B. the |keyHash| has already been distributed. */
|
||||||
|
|
||||||
|
@ -543,7 +508,7 @@ class HashTable : private AllocPolicy
|
||||||
Entry *entry = &table[h1];
|
Entry *entry = &table[h1];
|
||||||
|
|
||||||
/* Miss: return space for a new entry. */
|
/* Miss: return space for a new entry. */
|
||||||
if (entry->isFree()) {
|
if (!entry->isLive()) {
|
||||||
METER(stats.misses++);
|
METER(stats.misses++);
|
||||||
return *entry;
|
return *entry;
|
||||||
}
|
}
|
||||||
|
@ -559,14 +524,16 @@ class HashTable : private AllocPolicy
|
||||||
h1 = applyDoubleHash(h1, dh);
|
h1 = applyDoubleHash(h1, dh);
|
||||||
|
|
||||||
entry = &table[h1];
|
entry = &table[h1];
|
||||||
if (entry->isFree()) {
|
if (!entry->isLive()) {
|
||||||
METER(stats.misses++);
|
METER(stats.misses++);
|
||||||
return *entry;
|
return *entry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool changeTableSize(int deltaLog2)
|
enum RebuildStatus { NotOverloaded, Rehashed, RehashFailed };
|
||||||
|
|
||||||
|
RebuildStatus changeTableSize(int deltaLog2)
|
||||||
{
|
{
|
||||||
/* Look, but don't touch, until we succeed in getting new entry store. */
|
/* Look, but don't touch, until we succeed in getting new entry store. */
|
||||||
Entry *oldTable = table;
|
Entry *oldTable = table;
|
||||||
|
@ -575,12 +542,12 @@ class HashTable : private AllocPolicy
|
||||||
uint32_t newCapacity = JS_BIT(newLog2);
|
uint32_t newCapacity = JS_BIT(newLog2);
|
||||||
if (newCapacity > sMaxCapacity) {
|
if (newCapacity > sMaxCapacity) {
|
||||||
this->reportAllocOverflow();
|
this->reportAllocOverflow();
|
||||||
return false;
|
return RehashFailed;
|
||||||
}
|
}
|
||||||
|
|
||||||
Entry *newTable = createTable(*this, newCapacity);
|
Entry *newTable = createTable(*this, newCapacity);
|
||||||
if (!newTable)
|
if (!newTable)
|
||||||
return false;
|
return RehashFailed;
|
||||||
|
|
||||||
/* We can't fail from here on, so update table parameters. */
|
/* We can't fail from here on, so update table parameters. */
|
||||||
setTableSizeLog2(newLog2);
|
setTableSizeLog2(newLog2);
|
||||||
|
@ -597,30 +564,13 @@ class HashTable : private AllocPolicy
|
||||||
}
|
}
|
||||||
|
|
||||||
destroyTable(*this, oldTable, oldCap);
|
destroyTable(*this, oldTable, oldCap);
|
||||||
return true;
|
return Rehashed;
|
||||||
}
|
}
|
||||||
|
|
||||||
void add(const Lookup &l, const Entry &e)
|
RebuildStatus checkOverloaded()
|
||||||
{
|
|
||||||
HashNumber keyHash = prepareHash(l);
|
|
||||||
Entry &entry = lookup(l, keyHash, sCollisionBit);
|
|
||||||
|
|
||||||
if (entry.isRemoved()) {
|
|
||||||
METER(stats.addOverRemoved++);
|
|
||||||
removedCount--;
|
|
||||||
keyHash |= sCollisionBit;
|
|
||||||
}
|
|
||||||
|
|
||||||
entry.t = e.t;
|
|
||||||
entry.setLive(keyHash);
|
|
||||||
entryCount++;
|
|
||||||
mutationCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool checkOverloaded()
|
|
||||||
{
|
{
|
||||||
if (!overloaded())
|
if (!overloaded())
|
||||||
return false;
|
return NotOverloaded;
|
||||||
|
|
||||||
/* Compress if a quarter or more of all entries are removed. */
|
/* Compress if a quarter or more of all entries are removed. */
|
||||||
int deltaLog2;
|
int deltaLog2;
|
||||||
|
@ -635,9 +585,21 @@ class HashTable : private AllocPolicy
|
||||||
return changeTableSize(deltaLog2);
|
return changeTableSize(deltaLog2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Infallibly rehash the table if we are overloaded with removals. */
|
||||||
|
void checkOverRemoved()
|
||||||
|
{
|
||||||
|
if (overloaded()) {
|
||||||
|
METER(stats.rehashes++);
|
||||||
|
rehashTable();
|
||||||
|
JS_ASSERT(!overloaded());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void remove(Entry &e)
|
void remove(Entry &e)
|
||||||
{
|
{
|
||||||
|
JS_ASSERT(table);
|
||||||
METER(stats.removes++);
|
METER(stats.removes++);
|
||||||
|
|
||||||
if (e.hasCollision()) {
|
if (e.hasCollision()) {
|
||||||
e.setRemoved();
|
e.setRemoved();
|
||||||
removedCount++;
|
removedCount++;
|
||||||
|
@ -657,6 +619,52 @@ class HashTable : private AllocPolicy
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is identical to changeTableSize(currentSize), but without requiring
|
||||||
|
* a second table. We do this by recycling the collision bits to tell us if
|
||||||
|
* the element is already inserted or still waiting to be inserted. Since
|
||||||
|
* already-inserted elements win any conflicts, we get the same table as we
|
||||||
|
* would have gotten through random insertion order.
|
||||||
|
*/
|
||||||
|
void rehashTable()
|
||||||
|
{
|
||||||
|
removedCount = 0;
|
||||||
|
for (size_t i = 0; i < capacity(); ++i)
|
||||||
|
table[i].unsetCollision();
|
||||||
|
|
||||||
|
for (size_t i = 0; i < capacity();) {
|
||||||
|
Entry *src = &table[i];
|
||||||
|
|
||||||
|
if (!src->isLive() || src->hasCollision()) {
|
||||||
|
++i;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
HashNumber keyHash = src->getKeyHash();
|
||||||
|
HashNumber h1 = hash1(keyHash, hashShift);
|
||||||
|
DoubleHash dh = hash2(keyHash, hashShift);
|
||||||
|
Entry *tgt = &table[h1];
|
||||||
|
while (true) {
|
||||||
|
if (!tgt->hasCollision()) {
|
||||||
|
Swap(*src, *tgt);
|
||||||
|
tgt->setCollision();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 = applyDoubleHash(h1, dh);
|
||||||
|
tgt = &table[h1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TODO: this algorithm leaves collision bits on *all* elements, even if
|
||||||
|
* they are on no collision path. We have the option of setting the
|
||||||
|
* collision bits correctly on a subsequent pass or skipping the rehash
|
||||||
|
* unless we are totally filled with tombstones: benchmark to find out
|
||||||
|
* which approach is best.
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void clear()
|
void clear()
|
||||||
{
|
{
|
||||||
|
@ -688,22 +696,27 @@ class HashTable : private AllocPolicy
|
||||||
}
|
}
|
||||||
|
|
||||||
Range all() const {
|
Range all() const {
|
||||||
|
JS_ASSERT(table);
|
||||||
return Range(table, table + capacity());
|
return Range(table, table + capacity());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool empty() const {
|
bool empty() const {
|
||||||
|
JS_ASSERT(table);
|
||||||
return !entryCount;
|
return !entryCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t count() const {
|
uint32_t count() const {
|
||||||
|
JS_ASSERT(table);
|
||||||
return entryCount;
|
return entryCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t capacity() const {
|
uint32_t capacity() const {
|
||||||
|
JS_ASSERT(table);
|
||||||
return JS_BIT(sHashBits - hashShift);
|
return JS_BIT(sHashBits - hashShift);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t generation() const {
|
uint32_t generation() const {
|
||||||
|
JS_ASSERT(table);
|
||||||
return gen;
|
return gen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -747,8 +760,11 @@ class HashTable : private AllocPolicy
|
||||||
removedCount--;
|
removedCount--;
|
||||||
p.keyHash |= sCollisionBit;
|
p.keyHash |= sCollisionBit;
|
||||||
} else {
|
} else {
|
||||||
if (checkOverloaded())
|
/* Preserve the validity of |p.entry|. */
|
||||||
/* Preserve the validity of |p.entry|. */
|
RebuildStatus status = checkOverloaded();
|
||||||
|
if (status == RehashFailed)
|
||||||
|
return false;
|
||||||
|
if (status == Rehashed)
|
||||||
p.entry = &findFreeEntry(p.keyHash);
|
p.entry = &findFreeEntry(p.keyHash);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -779,6 +795,34 @@ class HashTable : private AllocPolicy
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void putNewInfallible(const Lookup &l, const T &t)
|
||||||
|
{
|
||||||
|
JS_ASSERT(table);
|
||||||
|
|
||||||
|
HashNumber keyHash = prepareHash(l);
|
||||||
|
Entry *entry = &findFreeEntry(keyHash);
|
||||||
|
|
||||||
|
if (entry->isRemoved()) {
|
||||||
|
METER(stats.addOverRemoved++);
|
||||||
|
removedCount--;
|
||||||
|
keyHash |= sCollisionBit;
|
||||||
|
}
|
||||||
|
|
||||||
|
entry->t = t;
|
||||||
|
entry->setLive(keyHash);
|
||||||
|
entryCount++;
|
||||||
|
mutationCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool putNew(const Lookup &l, const T &t)
|
||||||
|
{
|
||||||
|
if (checkOverloaded() == RehashFailed)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
putNewInfallible(l, t);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool relookupOrAdd(AddPtr& p, const Lookup &l, const T& t)
|
bool relookupOrAdd(AddPtr& p, const Lookup &l, const T& t)
|
||||||
{
|
{
|
||||||
p.mutationCount = mutationCount;
|
p.mutationCount = mutationCount;
|
||||||
|
@ -791,6 +835,7 @@ class HashTable : private AllocPolicy
|
||||||
|
|
||||||
void remove(Ptr p)
|
void remove(Ptr p)
|
||||||
{
|
{
|
||||||
|
JS_ASSERT(table);
|
||||||
ReentrancyGuard g(*this);
|
ReentrancyGuard g(*this);
|
||||||
JS_ASSERT(p.found());
|
JS_ASSERT(p.found());
|
||||||
remove(*p.entry);
|
remove(*p.entry);
|
||||||
|
@ -1163,9 +1208,7 @@ class HashMap
|
||||||
|
|
||||||
/* Like put, but assert that the given key is not already present. */
|
/* Like put, but assert that the given key is not already present. */
|
||||||
bool putNew(const Key &k, const Value &v) {
|
bool putNew(const Key &k, const Value &v) {
|
||||||
AddPtr p = lookupForAdd(k);
|
return impl.putNew(k, Entry(k, v));
|
||||||
JS_ASSERT(!p);
|
|
||||||
return add(p, k, v);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add (k,defaultValue) if k no found. Return false-y Ptr on oom. */
|
/* Add (k,defaultValue) if k no found. Return false-y Ptr on oom. */
|
||||||
|
@ -1371,15 +1414,11 @@ class HashSet
|
||||||
|
|
||||||
/* Like put, but assert that the given key is not already present. */
|
/* Like put, but assert that the given key is not already present. */
|
||||||
bool putNew(const T &t) {
|
bool putNew(const T &t) {
|
||||||
AddPtr p = lookupForAdd(t);
|
return impl.putNew(t, t);
|
||||||
JS_ASSERT(!p);
|
|
||||||
return add(p, t);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool putNew(const Lookup &l, const T &t) {
|
bool putNew(const Lookup &l, const T &t) {
|
||||||
AddPtr p = lookupForAdd(l);
|
return impl.putNew(l, t);
|
||||||
JS_ASSERT(!p);
|
|
||||||
return add(p, t);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void remove(const Lookup &l) {
|
void remove(const Lookup &l) {
|
||||||
|
|
|
@ -1,40 +1,7 @@
|
||||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
/* ***** BEGIN LICENSE BLOCK *****
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
* 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/. */
|
||||||
* 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.
|
* This section typedefs the old 'native' types to the new <stdint.h> types.
|
||||||
|
|
|
@ -1,41 +1,9 @@
|
||||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||||
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
|
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
|
||||||
*
|
*
|
||||||
* ***** BEGIN LICENSE BLOCK *****
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
* 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/. */
|
||||||
* 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
|
#ifndef js_MemoryMetrics_h
|
||||||
#define js_MemoryMetrics_h
|
#define js_MemoryMetrics_h
|
||||||
|
@ -62,6 +30,53 @@ struct TypeInferenceSizes
|
||||||
size_t objects;
|
size_t objects;
|
||||||
size_t tables;
|
size_t tables;
|
||||||
size_t temporary;
|
size_t temporary;
|
||||||
|
|
||||||
|
void add(TypeInferenceSizes &sizes) {
|
||||||
|
this->scripts += sizes.scripts;
|
||||||
|
this->objects += sizes.objects;
|
||||||
|
this->tables += sizes.tables;
|
||||||
|
this->temporary += sizes.temporary;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// These measurements relate directly to the JSRuntime, and not to
|
||||||
|
// compartments within it.
|
||||||
|
struct RuntimeSizes
|
||||||
|
{
|
||||||
|
RuntimeSizes()
|
||||||
|
: object(0)
|
||||||
|
, atomsTable(0)
|
||||||
|
, contexts(0)
|
||||||
|
, dtoa(0)
|
||||||
|
, temporary(0)
|
||||||
|
, mjitCode(0)
|
||||||
|
, regexpCode(0)
|
||||||
|
, unusedCodeMemory(0)
|
||||||
|
, stackCommitted(0)
|
||||||
|
, gcMarker(0)
|
||||||
|
, mathCache(0)
|
||||||
|
, scriptFilenames(0)
|
||||||
|
, compartmentObjects(0)
|
||||||
|
{}
|
||||||
|
|
||||||
|
size_t object;
|
||||||
|
size_t atomsTable;
|
||||||
|
size_t contexts;
|
||||||
|
size_t dtoa;
|
||||||
|
size_t temporary;
|
||||||
|
size_t mjitCode;
|
||||||
|
size_t regexpCode;
|
||||||
|
size_t unusedCodeMemory;
|
||||||
|
size_t stackCommitted;
|
||||||
|
size_t gcMarker;
|
||||||
|
size_t mathCache;
|
||||||
|
size_t scriptFilenames;
|
||||||
|
|
||||||
|
// This is the exception to the "RuntimeSizes doesn't measure things within
|
||||||
|
// compartments" rule. We combine the sizes of all the JSCompartment
|
||||||
|
// objects into a single measurement because each one is fairly small, and
|
||||||
|
// they're all the same size.
|
||||||
|
size_t compartmentObjects;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CompartmentStats
|
struct CompartmentStats
|
||||||
|
@ -70,10 +85,14 @@ struct CompartmentStats
|
||||||
memset(this, 0, sizeof(*this));
|
memset(this, 0, sizeof(*this));
|
||||||
}
|
}
|
||||||
|
|
||||||
void *extra;
|
// These fields can be used by embedders.
|
||||||
size_t gcHeapArenaHeaders;
|
void *extra1;
|
||||||
size_t gcHeapArenaPadding;
|
void *extra2;
|
||||||
size_t gcHeapArenaUnused;
|
|
||||||
|
// If you add a new number, remember to update add() and maybe
|
||||||
|
// gcHeapThingsSize()!
|
||||||
|
size_t gcHeapArenaAdmin;
|
||||||
|
size_t gcHeapUnusedGcThings;
|
||||||
|
|
||||||
size_t gcHeapObjectsNonFunction;
|
size_t gcHeapObjectsNonFunction;
|
||||||
size_t gcHeapObjectsFunction;
|
size_t gcHeapObjectsFunction;
|
||||||
|
@ -83,83 +102,116 @@ struct CompartmentStats
|
||||||
size_t gcHeapShapesBase;
|
size_t gcHeapShapesBase;
|
||||||
size_t gcHeapScripts;
|
size_t gcHeapScripts;
|
||||||
size_t gcHeapTypeObjects;
|
size_t gcHeapTypeObjects;
|
||||||
|
#if JS_HAS_XML_SUPPORT
|
||||||
size_t gcHeapXML;
|
size_t gcHeapXML;
|
||||||
|
#endif
|
||||||
|
|
||||||
size_t objectSlots;
|
size_t objectSlots;
|
||||||
size_t objectElements;
|
size_t objectElements;
|
||||||
size_t objectMisc;
|
size_t objectMisc;
|
||||||
|
size_t objectPrivate;
|
||||||
size_t stringChars;
|
size_t stringChars;
|
||||||
size_t shapesExtraTreeTables;
|
size_t shapesExtraTreeTables;
|
||||||
size_t shapesExtraDictTables;
|
size_t shapesExtraDictTables;
|
||||||
size_t shapesExtraTreeShapeKids;
|
size_t shapesExtraTreeShapeKids;
|
||||||
size_t shapesCompartmentTables;
|
size_t shapesCompartmentTables;
|
||||||
size_t scriptData;
|
size_t scriptData;
|
||||||
|
|
||||||
#ifdef JS_METHODJIT
|
|
||||||
size_t mjitCode;
|
|
||||||
size_t mjitData;
|
size_t mjitData;
|
||||||
#endif
|
size_t crossCompartmentWrappers;
|
||||||
|
|
||||||
TypeInferenceSizes typeInferenceSizes;
|
TypeInferenceSizes typeInferenceSizes;
|
||||||
|
|
||||||
|
// Add cStats's numbers to this object's numbers.
|
||||||
|
void add(CompartmentStats &cStats) {
|
||||||
|
#define ADD(x) this->x += cStats.x
|
||||||
|
|
||||||
|
ADD(gcHeapArenaAdmin);
|
||||||
|
ADD(gcHeapUnusedGcThings);
|
||||||
|
|
||||||
|
ADD(gcHeapObjectsNonFunction);
|
||||||
|
ADD(gcHeapObjectsFunction);
|
||||||
|
ADD(gcHeapStrings);
|
||||||
|
ADD(gcHeapShapesTree);
|
||||||
|
ADD(gcHeapShapesDict);
|
||||||
|
ADD(gcHeapShapesBase);
|
||||||
|
ADD(gcHeapScripts);
|
||||||
|
ADD(gcHeapTypeObjects);
|
||||||
|
#if JS_HAS_XML_SUPPORT
|
||||||
|
ADD(gcHeapXML);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ADD(objectSlots);
|
||||||
|
ADD(objectElements);
|
||||||
|
ADD(objectMisc);
|
||||||
|
ADD(objectPrivate);
|
||||||
|
ADD(stringChars);
|
||||||
|
ADD(shapesExtraTreeTables);
|
||||||
|
ADD(shapesExtraDictTables);
|
||||||
|
ADD(shapesExtraTreeShapeKids);
|
||||||
|
ADD(shapesCompartmentTables);
|
||||||
|
ADD(scriptData);
|
||||||
|
ADD(mjitData);
|
||||||
|
ADD(crossCompartmentWrappers);
|
||||||
|
|
||||||
|
#undef ADD
|
||||||
|
|
||||||
|
typeInferenceSizes.add(cStats.typeInferenceSizes);
|
||||||
|
}
|
||||||
|
|
||||||
|
// The size of all the live things in the GC heap.
|
||||||
|
size_t gcHeapThingsSize();
|
||||||
};
|
};
|
||||||
|
|
||||||
struct RuntimeStats
|
struct RuntimeStats
|
||||||
{
|
{
|
||||||
RuntimeStats(JSMallocSizeOfFun mallocSizeOf)
|
RuntimeStats(JSMallocSizeOfFun mallocSizeOf)
|
||||||
: runtimeObject(0)
|
: runtime()
|
||||||
, runtimeAtomsTable(0)
|
|
||||||
, runtimeContexts(0)
|
|
||||||
, runtimeNormal(0)
|
|
||||||
, runtimeTemporary(0)
|
|
||||||
, runtimeRegexpCode(0)
|
|
||||||
, runtimeStackCommitted(0)
|
|
||||||
, runtimeGCMarker(0)
|
|
||||||
, gcHeapChunkTotal(0)
|
, gcHeapChunkTotal(0)
|
||||||
, gcHeapChunkCleanUnused(0)
|
, gcHeapDecommittedArenas(0)
|
||||||
, gcHeapChunkDirtyUnused(0)
|
, gcHeapUnusedChunks(0)
|
||||||
, gcHeapChunkCleanDecommitted(0)
|
, gcHeapUnusedArenas(0)
|
||||||
, gcHeapChunkDirtyDecommitted(0)
|
, gcHeapUnusedGcThings(0)
|
||||||
, gcHeapArenaUnused(0)
|
|
||||||
, gcHeapChunkAdmin(0)
|
, gcHeapChunkAdmin(0)
|
||||||
, gcHeapUnusedPercentage(0)
|
, gcHeapGcThings(0)
|
||||||
, totalObjects(0)
|
, totals()
|
||||||
, totalShapes(0)
|
|
||||||
, totalScripts(0)
|
|
||||||
, totalStrings(0)
|
|
||||||
#ifdef JS_METHODJIT
|
|
||||||
, totalMjit(0)
|
|
||||||
#endif
|
|
||||||
, totalTypeInference(0)
|
|
||||||
, totalAnalysisTemp(0)
|
|
||||||
, compartmentStatsVector()
|
, compartmentStatsVector()
|
||||||
, currCompartmentStats(NULL)
|
, currCompartmentStats(NULL)
|
||||||
, mallocSizeOf(mallocSizeOf)
|
, mallocSizeOf(mallocSizeOf)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
size_t runtimeObject;
|
RuntimeSizes runtime;
|
||||||
size_t runtimeAtomsTable;
|
|
||||||
size_t runtimeContexts;
|
// If you add a new number, remember to update the constructor!
|
||||||
size_t runtimeNormal;
|
|
||||||
size_t runtimeTemporary;
|
// Here's a useful breakdown of the GC heap.
|
||||||
size_t runtimeRegexpCode;
|
//
|
||||||
size_t runtimeStackCommitted;
|
// - rtStats.gcHeapChunkTotal
|
||||||
size_t runtimeGCMarker;
|
// - decommitted bytes
|
||||||
|
// - rtStats.gcHeapDecommittedArenas (decommitted arenas in non-empty chunks)
|
||||||
|
// - unused bytes
|
||||||
|
// - rtStats.gcHeapUnusedChunks (empty chunks)
|
||||||
|
// - rtStats.gcHeapUnusedArenas (empty arenas within non-empty chunks)
|
||||||
|
// - rtStats.total.gcHeapUnusedGcThings (empty GC thing slots within non-empty arenas)
|
||||||
|
// - used bytes
|
||||||
|
// - rtStats.gcHeapChunkAdmin
|
||||||
|
// - rtStats.total.gcHeapArenaAdmin
|
||||||
|
// - rtStats.gcHeapGcThings (in-use GC things)
|
||||||
|
//
|
||||||
|
// It's possible that some arenas in empty chunks may be decommitted, but
|
||||||
|
// we don't count those under rtStats.gcHeapDecommittedArenas because (a)
|
||||||
|
// it's rare, and (b) this means that rtStats.gcHeapUnusedChunks is a
|
||||||
|
// multiple of the chunk size, which is good.
|
||||||
|
|
||||||
size_t gcHeapChunkTotal;
|
size_t gcHeapChunkTotal;
|
||||||
size_t gcHeapChunkCleanUnused;
|
size_t gcHeapDecommittedArenas;
|
||||||
size_t gcHeapChunkDirtyUnused;
|
size_t gcHeapUnusedChunks;
|
||||||
size_t gcHeapChunkCleanDecommitted;
|
size_t gcHeapUnusedArenas;
|
||||||
size_t gcHeapChunkDirtyDecommitted;
|
size_t gcHeapUnusedGcThings;
|
||||||
size_t gcHeapArenaUnused;
|
|
||||||
size_t gcHeapChunkAdmin;
|
size_t gcHeapChunkAdmin;
|
||||||
size_t gcHeapUnusedPercentage;
|
size_t gcHeapGcThings;
|
||||||
size_t totalObjects;
|
|
||||||
size_t totalShapes;
|
// The sum of all compartment's measurements.
|
||||||
size_t totalScripts;
|
CompartmentStats totals;
|
||||||
size_t totalStrings;
|
|
||||||
#ifdef JS_METHODJIT
|
|
||||||
size_t totalMjit;
|
|
||||||
#endif
|
|
||||||
size_t totalTypeInference;
|
|
||||||
size_t totalAnalysisTemp;
|
|
||||||
|
|
||||||
js::Vector<CompartmentStats, 0, js::SystemAllocPolicy> compartmentStatsVector;
|
js::Vector<CompartmentStats, 0, js::SystemAllocPolicy> compartmentStatsVector;
|
||||||
CompartmentStats *currCompartmentStats;
|
CompartmentStats *currCompartmentStats;
|
||||||
|
@ -171,8 +223,16 @@ struct RuntimeStats
|
||||||
|
|
||||||
#ifdef JS_THREADSAFE
|
#ifdef JS_THREADSAFE
|
||||||
|
|
||||||
|
class ObjectPrivateVisitor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// Within CollectRuntimeStats, this method is called for each JS object
|
||||||
|
// that has a private slot containing an nsISupports pointer.
|
||||||
|
virtual size_t sizeOfIncludingThis(void *aSupports) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
extern JS_PUBLIC_API(bool)
|
extern JS_PUBLIC_API(bool)
|
||||||
CollectRuntimeStats(JSRuntime *rt, RuntimeStats *rtStats);
|
CollectRuntimeStats(JSRuntime *rt, RuntimeStats *rtStats, ObjectPrivateVisitor *opv);
|
||||||
|
|
||||||
extern JS_PUBLIC_API(int64_t)
|
extern JS_PUBLIC_API(int64_t)
|
||||||
GetExplicitNonHeapForRuntime(JSRuntime *rt, JSMallocSizeOfFun mallocSizeOf);
|
GetExplicitNonHeapForRuntime(JSRuntime *rt, JSMallocSizeOfFun mallocSizeOf);
|
||||||
|
|
|
@ -1,42 +1,9 @@
|
||||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||||
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
|
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
|
||||||
*
|
*
|
||||||
* ***** BEGIN LICENSE BLOCK *****
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
* 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/. */
|
||||||
* 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__
|
#ifndef js_template_lib_h__
|
||||||
#define js_template_lib_h__
|
#define js_template_lib_h__
|
||||||
|
@ -174,10 +141,13 @@ template <typename T> struct IsPodType<T *> { static const bool result =
|
||||||
template <bool cond, typename T, T v1, T v2> struct If { static const T result = v1; };
|
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; };
|
template <typename T, T v1, T v2> struct If<false, T, v1, v2> { static const T result = v2; };
|
||||||
|
|
||||||
|
template <class T> struct IsPointerType { static const bool result = false; };
|
||||||
|
template <class T> struct IsPointerType<T *> { static const bool result = true; };
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Traits class for identifying types that are implicitly barriered.
|
* Traits class for identifying types that are implicitly barriered.
|
||||||
*/
|
*/
|
||||||
template <class T> struct IsPostBarrieredType { static const bool result = false; };
|
template <class T> struct IsRelocatableHeapType { static const bool result = true; };
|
||||||
|
|
||||||
} /* namespace tl */
|
} /* namespace tl */
|
||||||
} /* namespace js */
|
} /* namespace js */
|
||||||
|
|
|
@ -1,46 +1,15 @@
|
||||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||||
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
|
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
|
||||||
*
|
*
|
||||||
* ***** BEGIN LICENSE BLOCK *****
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
* 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/. */
|
||||||
* 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):
|
|
||||||
*
|
|
||||||
* 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_utility_h__
|
#ifndef js_utility_h__
|
||||||
#define js_utility_h__
|
#define js_utility_h__
|
||||||
|
|
||||||
#include "mozilla/Assertions.h"
|
#include "mozilla/Assertions.h"
|
||||||
|
#include "mozilla/Attributes.h"
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
@ -53,6 +22,7 @@
|
||||||
#include "jstypes.h"
|
#include "jstypes.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
# include "mozilla/Scoped.h"
|
||||||
|
|
||||||
/* The public JS engine namespace. */
|
/* The public JS engine namespace. */
|
||||||
namespace JS {}
|
namespace JS {}
|
||||||
|
@ -97,6 +67,9 @@ JS_BEGIN_EXTERN_C
|
||||||
#define JS_STATIC_ASSERT(cond) MOZ_STATIC_ASSERT(cond, "JS_STATIC_ASSERT")
|
#define JS_STATIC_ASSERT(cond) MOZ_STATIC_ASSERT(cond, "JS_STATIC_ASSERT")
|
||||||
#define JS_STATIC_ASSERT_IF(cond, expr) MOZ_STATIC_ASSERT_IF(cond, expr, "JS_STATIC_ASSERT_IF")
|
#define JS_STATIC_ASSERT_IF(cond, expr) MOZ_STATIC_ASSERT_IF(cond, expr, "JS_STATIC_ASSERT_IF")
|
||||||
|
|
||||||
|
extern MOZ_NORETURN JS_PUBLIC_API(void)
|
||||||
|
JS_Assert(const char *s, const char *file, int ln);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Abort the process in a non-graceful manner. This will cause a core file,
|
* 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
|
* call to the debugger or other moral equivalent as well as causing the
|
||||||
|
@ -626,6 +599,15 @@ public:
|
||||||
class UnwantedForeground : public Foreground {
|
class UnwantedForeground : public Foreground {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct ScopedDeletePtrTraits
|
||||||
|
{
|
||||||
|
typedef T *type;
|
||||||
|
static T *empty() { return NULL; }
|
||||||
|
static void release(T *ptr) { Foreground::delete_(ptr); }
|
||||||
|
};
|
||||||
|
SCOPED_TEMPLATE(ScopedDeletePtr, ScopedDeletePtrTraits)
|
||||||
|
|
||||||
} /* namespace js */
|
} /* namespace js */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -847,7 +829,7 @@ class MoveRef {
|
||||||
explicit MoveRef(T &t) : pointer(&t) { }
|
explicit MoveRef(T &t) : pointer(&t) { }
|
||||||
T &operator*() const { return *pointer; }
|
T &operator*() const { return *pointer; }
|
||||||
T *operator->() const { return pointer; }
|
T *operator->() const { return pointer; }
|
||||||
#ifdef __GXX_EXPERIMENTAL_CXX0X__
|
#if defined(__GXX_EXPERIMENTAL_CXX0X__) && defined(__clang__)
|
||||||
/*
|
/*
|
||||||
* If MoveRef is used in a rvalue position (which is expected), we can
|
* If MoveRef is used in a rvalue position (which is expected), we can
|
||||||
* end up in a situation where, without this ifdef, we would try to pass
|
* end up in a situation where, without this ifdef, we would try to pass
|
||||||
|
|
|
@ -1,42 +1,9 @@
|
||||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||||
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
|
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
|
||||||
*
|
*
|
||||||
* ***** BEGIN LICENSE BLOCK *****
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
* 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/. */
|
||||||
* 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
|
|
||||||
* June 12, 2009.
|
|
||||||
*
|
|
||||||
* The Initial Developer of the Original Code is
|
|
||||||
* the Mozilla Corporation.
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* Luke Wagner <lw@mozilla.com>
|
|
||||||
* Nicholas Nethercote <nnethercote@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 jsvector_h_
|
#ifndef jsvector_h_
|
||||||
#define jsvector_h_
|
#define jsvector_h_
|
||||||
|
@ -213,7 +180,7 @@ struct VectorImpl<T, N, AP, true>
|
||||||
template <class T, size_t N, class AllocPolicy>
|
template <class T, size_t N, class AllocPolicy>
|
||||||
class Vector : private AllocPolicy
|
class Vector : private AllocPolicy
|
||||||
{
|
{
|
||||||
typedef typename tl::StaticAssert<!tl::IsPostBarrieredType<T>::result>::result _;
|
typedef typename tl::StaticAssert<tl::IsRelocatableHeapType<T>::result>::result _;
|
||||||
|
|
||||||
/* utilities */
|
/* utilities */
|
||||||
|
|
||||||
|
@ -596,7 +563,12 @@ Vector<T,N,AP>::~Vector()
|
||||||
*/
|
*/
|
||||||
template <class T, size_t N, class AP>
|
template <class T, size_t N, class AP>
|
||||||
STATIC_POSTCONDITION(!return || newCap >= curLength + lengthInc)
|
STATIC_POSTCONDITION(!return || newCap >= curLength + lengthInc)
|
||||||
|
#ifdef DEBUG
|
||||||
|
/* gcc (ARM, x86) compiler bug workaround - See bug 694694 */
|
||||||
|
JS_NEVER_INLINE bool
|
||||||
|
#else
|
||||||
inline bool
|
inline bool
|
||||||
|
#endif
|
||||||
Vector<T,N,AP>::calculateNewCapacity(size_t curLength, size_t lengthInc,
|
Vector<T,N,AP>::calculateNewCapacity(size_t curLength, size_t lengthInc,
|
||||||
size_t &newCap)
|
size_t &newCap)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,40 +1,9 @@
|
||||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||||
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
|
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
|
||||||
*
|
*
|
||||||
* ***** BEGIN LICENSE BLOCK *****
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
* 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/. */
|
||||||
* 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_
|
#ifndef jsalloc_h_
|
||||||
#define jsalloc_h_
|
#define jsalloc_h_
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
e71bf3943ff22eeb475acd419c7005556859f6c4
|
37b6af08d1e6059f152ae515d8d7422a346cf7ed
|
|
@ -1,41 +1,8 @@
|
||||||
/* -*- 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 *****
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
* 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/. */
|
||||||
* 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___
|
#ifndef jsatom_h___
|
||||||
#define jsatom_h___
|
#define jsatom_h___
|
||||||
|
@ -67,14 +34,37 @@ JSID_FROM_BITS(size_t bits)
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Must not be used on atoms that are representable as integer jsids.
|
||||||
|
* Prefer NameToId or AtomToId over this function:
|
||||||
|
*
|
||||||
|
* A PropertyName is an atom that does not contain an integer in the range
|
||||||
|
* [0, UINT32_MAX]. However, jsid can only hold an integer in the range
|
||||||
|
* [0, JSID_INT_MAX] (where JSID_INT_MAX == 2^31-1). Thus, for the range of
|
||||||
|
* integers (JSID_INT_MAX, UINT32_MAX], to represent as a jsid 'id', it must be
|
||||||
|
* the case JSID_IS_ATOM(id) and !JSID_TO_ATOM(id)->isPropertyName(). In most
|
||||||
|
* cases when creating a jsid, code does not have to care about this corner
|
||||||
|
* case because:
|
||||||
|
*
|
||||||
|
* - When given an arbitrary JSAtom*, AtomToId must be used, which checks for
|
||||||
|
* integer atoms representable as integer jsids, and does this conversion.
|
||||||
|
*
|
||||||
|
* - When given a PropertyName*, NameToId can be used which which does not need
|
||||||
|
* to do any dynamic checks.
|
||||||
|
*
|
||||||
|
* Thus, it is only the rare third case which needs this function, which
|
||||||
|
* handles any JSAtom* that is known not to be representable with an int jsid.
|
||||||
|
*/
|
||||||
static JS_ALWAYS_INLINE jsid
|
static JS_ALWAYS_INLINE jsid
|
||||||
ATOM_TO_JSID(JSAtom *atom)
|
NON_INTEGER_ATOM_TO_JSID(JSAtom *atom)
|
||||||
{
|
{
|
||||||
JS_ASSERT(((size_t)atom & 0x7) == 0);
|
JS_ASSERT(((size_t)atom & 0x7) == 0);
|
||||||
return JSID_FROM_BITS((size_t)atom);
|
jsid id = JSID_FROM_BITS((size_t)atom);
|
||||||
|
JS_ASSERT(id == INTERNED_STRING_TO_JSID(NULL, (JSString*)atom));
|
||||||
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* All strings stored in jsids are atomized. */
|
/* All strings stored in jsids are atomized, but are not necessarily property names. */
|
||||||
static JS_ALWAYS_INLINE JSBool
|
static JS_ALWAYS_INLINE JSBool
|
||||||
JSID_IS_ATOM(jsid id)
|
JSID_IS_ATOM(jsid id)
|
||||||
{
|
{
|
||||||
|
@ -84,7 +74,7 @@ JSID_IS_ATOM(jsid id)
|
||||||
static JS_ALWAYS_INLINE JSBool
|
static JS_ALWAYS_INLINE JSBool
|
||||||
JSID_IS_ATOM(jsid id, JSAtom *atom)
|
JSID_IS_ATOM(jsid id, JSAtom *atom)
|
||||||
{
|
{
|
||||||
return JSID_BITS(id) == JSID_BITS(ATOM_TO_JSID(atom));
|
return id == JSID_FROM_BITS((size_t)atom);
|
||||||
}
|
}
|
||||||
|
|
||||||
static JS_ALWAYS_INLINE JSAtom *
|
static JS_ALWAYS_INLINE JSAtom *
|
||||||
|
@ -93,9 +83,6 @@ JSID_TO_ATOM(jsid id)
|
||||||
return (JSAtom *)JSID_TO_STRING(id);
|
return (JSAtom *)JSID_TO_STRING(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern jsid
|
|
||||||
js_CheckForStringIndex(jsid id);
|
|
||||||
|
|
||||||
JS_STATIC_ASSERT(sizeof(JSHashNumber) == 4);
|
JS_STATIC_ASSERT(sizeof(JSHashNumber) == 4);
|
||||||
JS_STATIC_ASSERT(sizeof(jsid) == JS_BYTES_PER_WORD);
|
JS_STATIC_ASSERT(sizeof(jsid) == JS_BYTES_PER_WORD);
|
||||||
|
|
||||||
|
@ -104,7 +91,6 @@ namespace js {
|
||||||
static JS_ALWAYS_INLINE JSHashNumber
|
static JS_ALWAYS_INLINE JSHashNumber
|
||||||
HashId(jsid id)
|
HashId(jsid id)
|
||||||
{
|
{
|
||||||
JS_ASSERT(js_CheckForStringIndex(id) == id);
|
|
||||||
JSHashNumber n =
|
JSHashNumber n =
|
||||||
#if JS_BYTES_PER_WORD == 4
|
#if JS_BYTES_PER_WORD == 4
|
||||||
JSHashNumber(JSID_BITS(id));
|
JSHashNumber(JSID_BITS(id));
|
||||||
|
@ -140,11 +126,9 @@ struct DefaultHasher<jsid>
|
||||||
{
|
{
|
||||||
typedef jsid Lookup;
|
typedef jsid Lookup;
|
||||||
static HashNumber hash(const Lookup &l) {
|
static HashNumber hash(const Lookup &l) {
|
||||||
JS_ASSERT(l == js_CheckForStringIndex(l));
|
|
||||||
return HashNumber(JSID_BITS(l));
|
return HashNumber(JSID_BITS(l));
|
||||||
}
|
}
|
||||||
static bool match(const jsid &id, const Lookup &l) {
|
static bool match(const jsid &id, const Lookup &l) {
|
||||||
JS_ASSERT(l == js_CheckForStringIndex(l));
|
|
||||||
return id == l;
|
return id == l;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -291,38 +275,7 @@ struct JSAtomState
|
||||||
#undef DEFINE_PROTOTYPE_ATOM
|
#undef DEFINE_PROTOTYPE_ATOM
|
||||||
#undef DEFINE_KEYWORD_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 commonAtomsOffset;
|
||||||
static const size_t lazyAtomsOffset;
|
|
||||||
|
|
||||||
void clearLazyAtoms() {
|
|
||||||
memset(&lazy, 0, sizeof(lazy));
|
|
||||||
}
|
|
||||||
|
|
||||||
void junkAtoms() {
|
void junkAtoms() {
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
@ -340,7 +293,7 @@ struct JSAtomState
|
||||||
extern bool
|
extern bool
|
||||||
AtomIsInterned(JSContext *cx, JSAtom *atom);
|
AtomIsInterned(JSContext *cx, JSAtom *atom);
|
||||||
|
|
||||||
#define ATOM(name) cx->runtime->atomState.name##Atom
|
#define ATOM(name) js::HandlePropertyName::fromMarkedLocation(&cx->runtime->atomState.name##Atom)
|
||||||
|
|
||||||
#define COMMON_ATOM_INDEX(name) \
|
#define COMMON_ATOM_INDEX(name) \
|
||||||
((offsetof(JSAtomState, name##Atom) - JSAtomState::commonAtomsOffset) \
|
((offsetof(JSAtomState, name##Atom) - JSAtomState::commonAtomsOffset) \
|
||||||
|
@ -349,10 +302,10 @@ AtomIsInterned(JSContext *cx, JSAtom *atom);
|
||||||
((offsetof(JSAtomState, typeAtoms[type]) - JSAtomState::commonAtomsOffset)\
|
((offsetof(JSAtomState, typeAtoms[type]) - JSAtomState::commonAtomsOffset)\
|
||||||
/ sizeof(JSAtom*))
|
/ sizeof(JSAtom*))
|
||||||
|
|
||||||
#define ATOM_OFFSET(name) offsetof(JSAtomState, name##Atom)
|
#define NAME_OFFSET(name) offsetof(JSAtomState, name##Atom)
|
||||||
#define OFFSET_TO_ATOM(rt,off) (*(JSAtom **)((char*)&(rt)->atomState + (off)))
|
#define OFFSET_TO_NAME(rt,off) (*(js::PropertyName **)((char*)&(rt)->atomState + (off)))
|
||||||
#define CLASS_ATOM_OFFSET(name) offsetof(JSAtomState, classAtoms[JSProto_##name])
|
#define CLASS_NAME_OFFSET(name) offsetof(JSAtomState, classAtoms[JSProto_##name])
|
||||||
#define CLASS_ATOM(cx,name) ((cx)->runtime->atomState.classAtoms[JSProto_##name])
|
#define CLASS_NAME(cx,name) ((cx)->runtime->atomState.classAtoms[JSProto_##name])
|
||||||
|
|
||||||
extern const char *const js_common_atom_names[];
|
extern const char *const js_common_atom_names[];
|
||||||
extern const size_t js_common_atom_count;
|
extern const size_t js_common_atom_count;
|
||||||
|
@ -457,28 +410,29 @@ js_DumpAtoms(JSContext *cx, FILE *fp);
|
||||||
|
|
||||||
#endif
|
#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 {
|
namespace js {
|
||||||
|
|
||||||
|
inline JSAtom *
|
||||||
|
ToAtom(JSContext *cx, const js::Value &v);
|
||||||
|
|
||||||
|
bool
|
||||||
|
InternNonIntElementId(JSContext *cx, JSObject *obj, const Value &idval,
|
||||||
|
jsid *idp, Value *vp);
|
||||||
|
|
||||||
|
inline bool
|
||||||
|
InternNonIntElementId(JSContext *cx, JSObject *obj, const Value &idval, jsid *idp)
|
||||||
|
{
|
||||||
|
Value dummy;
|
||||||
|
return InternNonIntElementId(cx, obj, idval, idp, &dummy);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For all unmapped atoms recorded in al, add a mapping from the atom's index
|
* 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
|
* 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.
|
* the list and map->vector must point to pre-allocated memory.
|
||||||
*/
|
*/
|
||||||
extern void
|
extern void
|
||||||
InitAtomMap(JSContext *cx, AtomIndexMap *indices, HeapPtrAtom *atoms);
|
InitAtomMap(JSContext *cx, AtomIndexMap *indices, HeapPtr<JSAtom> *atoms);
|
||||||
|
|
||||||
template<XDRMode mode>
|
template<XDRMode mode>
|
||||||
bool
|
bool
|
||||||
|
|
|
@ -118,8 +118,33 @@ DEFINE_ATOM(hasOwn, "hasOwn")
|
||||||
DEFINE_ATOM(keys, "keys")
|
DEFINE_ATOM(keys, "keys")
|
||||||
DEFINE_ATOM(iterate, "iterate")
|
DEFINE_ATOM(iterate, "iterate")
|
||||||
DEFINE_PROTOTYPE_ATOM(WeakMap)
|
DEFINE_PROTOTYPE_ATOM(WeakMap)
|
||||||
|
DEFINE_ATOM(buffer, "buffer")
|
||||||
DEFINE_ATOM(byteLength, "byteLength")
|
DEFINE_ATOM(byteLength, "byteLength")
|
||||||
|
DEFINE_ATOM(byteOffset, "byteOffset")
|
||||||
DEFINE_KEYWORD_ATOM(return)
|
DEFINE_KEYWORD_ATOM(return)
|
||||||
DEFINE_KEYWORD_ATOM(throw)
|
DEFINE_KEYWORD_ATOM(throw)
|
||||||
DEFINE_ATOM(url, "url")
|
DEFINE_ATOM(url, "url")
|
||||||
DEFINE_ATOM(innermost, "innermost")
|
DEFINE_ATOM(innermost, "innermost")
|
||||||
|
|
||||||
|
DEFINE_ATOM(XMLList, "XMLList")
|
||||||
|
DEFINE_ATOM(decodeURI, "decodeURI")
|
||||||
|
DEFINE_ATOM(decodeURIComponent, "decodeURIComponent")
|
||||||
|
DEFINE_ATOM(defineGetter, "__defineGetter__")
|
||||||
|
DEFINE_ATOM(defineSetter, "__defineSetter__")
|
||||||
|
DEFINE_ATOM(encodeURI, "encodeURI")
|
||||||
|
DEFINE_ATOM(encodeURIComponent, "encodeURIComponent")
|
||||||
|
DEFINE_ATOM(escape, "escape")
|
||||||
|
DEFINE_ATOM(hasOwnProperty, "hasOwnProperty")
|
||||||
|
DEFINE_ATOM(isFinite, "isFinite")
|
||||||
|
DEFINE_ATOM(isNaN, "isNaN")
|
||||||
|
DEFINE_ATOM(isPrototypeOf, "isPrototypeOf")
|
||||||
|
DEFINE_ATOM(isXMLName, "isXMLName")
|
||||||
|
DEFINE_ATOM(lookupGetter, "__lookupGetter__")
|
||||||
|
DEFINE_ATOM(lookupSetter, "__lookupSetter__")
|
||||||
|
DEFINE_ATOM(parseFloat, "parseFloat")
|
||||||
|
DEFINE_ATOM(parseInt, "parseInt")
|
||||||
|
DEFINE_ATOM(propertyIsEnumerable, "propertyIsEnumerable")
|
||||||
|
DEFINE_ATOM(unescape, "unescape")
|
||||||
|
DEFINE_ATOM(uneval, "uneval")
|
||||||
|
DEFINE_ATOM(unwatch, "unwatch")
|
||||||
|
DEFINE_ATOM(watch, "watch")
|
||||||
|
|
|
@ -1,119 +0,0 @@
|
||||||
/* -*- 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___ */
|
|
|
@ -1,41 +1,9 @@
|
||||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||||
* vim: set ts=4 sw=4 et tw=79 ft=cpp:
|
* vim: set ts=4 sw=4 et tw=79 ft=cpp:
|
||||||
*
|
*
|
||||||
* ***** BEGIN LICENSE BLOCK *****
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
* 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/. */
|
||||||
* 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__
|
#ifndef jsclass_h__
|
||||||
#define jsclass_h__
|
#define jsclass_h__
|
||||||
|
@ -54,6 +22,7 @@ namespace js {
|
||||||
|
|
||||||
class PropertyName;
|
class PropertyName;
|
||||||
class SpecialId;
|
class SpecialId;
|
||||||
|
class PropertyId;
|
||||||
|
|
||||||
static JS_ALWAYS_INLINE jsid
|
static JS_ALWAYS_INLINE jsid
|
||||||
SPECIALID_TO_JSID(const SpecialId &sid);
|
SPECIALID_TO_JSID(const SpecialId &sid);
|
||||||
|
@ -69,12 +38,13 @@ SPECIALID_TO_JSID(const SpecialId &sid);
|
||||||
* does not occur in JS scripts but may be used to indicate the absence of a
|
* 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.
|
* valid identifier; or JS_DEFAULT_XML_NAMESPACE_ID, if E4X is enabled.
|
||||||
*/
|
*/
|
||||||
|
class SpecialId
|
||||||
class SpecialId {
|
{
|
||||||
uintptr_t bits;
|
uintptr_t bits;
|
||||||
|
|
||||||
/* Needs access to raw bits. */
|
/* Needs access to raw bits. */
|
||||||
friend JS_ALWAYS_INLINE jsid SPECIALID_TO_JSID(const SpecialId &sid);
|
friend JS_ALWAYS_INLINE jsid SPECIALID_TO_JSID(const SpecialId &sid);
|
||||||
|
friend class PropertyId;
|
||||||
|
|
||||||
static const uintptr_t TYPE_VOID = JSID_TYPE_VOID;
|
static const uintptr_t TYPE_VOID = JSID_TYPE_VOID;
|
||||||
static const uintptr_t TYPE_OBJECT = JSID_TYPE_OBJECT;
|
static const uintptr_t TYPE_OBJECT = JSID_TYPE_OBJECT;
|
||||||
|
@ -174,83 +144,75 @@ JSID_TO_SPECIALID(jsid id)
|
||||||
return SpecialId::defaultXMLNamespace();
|
return SpecialId::defaultXMLNamespace();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef JS::Handle<SpecialId> HandleSpecialId;
|
||||||
|
|
||||||
/* js::Class operation signatures. */
|
/* js::Class operation signatures. */
|
||||||
|
|
||||||
typedef JSBool
|
typedef JSBool
|
||||||
(* LookupGenericOp)(JSContext *cx, JSObject *obj, jsid id, JSObject **objp,
|
(* LookupGenericOp)(JSContext *cx, HandleObject obj, HandleId id,
|
||||||
JSProperty **propp);
|
MutableHandleObject objp, MutableHandleShape propp);
|
||||||
typedef JSBool
|
typedef JSBool
|
||||||
(* LookupPropOp)(JSContext *cx, JSObject *obj, PropertyName *name, JSObject **objp,
|
(* LookupPropOp)(JSContext *cx, HandleObject obj, HandlePropertyName name,
|
||||||
JSProperty **propp);
|
MutableHandleObject objp, MutableHandleShape propp);
|
||||||
typedef JSBool
|
typedef JSBool
|
||||||
(* LookupElementOp)(JSContext *cx, JSObject *obj, uint32_t index, JSObject **objp,
|
(* LookupElementOp)(JSContext *cx, HandleObject obj, uint32_t index,
|
||||||
JSProperty **propp);
|
MutableHandleObject objp, MutableHandleShape propp);
|
||||||
typedef JSBool
|
typedef JSBool
|
||||||
(* LookupSpecialOp)(JSContext *cx, JSObject *obj, SpecialId sid, JSObject **objp,
|
(* LookupSpecialOp)(JSContext *cx, HandleObject obj, HandleSpecialId sid,
|
||||||
JSProperty **propp);
|
MutableHandleObject objp, MutableHandleShape propp);
|
||||||
typedef JSBool
|
typedef JSBool
|
||||||
(* DefineGenericOp)(JSContext *cx, JSObject *obj, jsid id, const Value *value,
|
(* DefineGenericOp)(JSContext *cx, HandleObject obj, HandleId id, const Value *value,
|
||||||
PropertyOp getter, StrictPropertyOp setter, unsigned attrs);
|
PropertyOp getter, StrictPropertyOp setter, unsigned attrs);
|
||||||
typedef JSBool
|
typedef JSBool
|
||||||
(* DefinePropOp)(JSContext *cx, JSObject *obj, PropertyName *name, const Value *value,
|
(* DefinePropOp)(JSContext *cx, HandleObject obj, HandlePropertyName name, const Value *value,
|
||||||
PropertyOp getter, StrictPropertyOp setter, unsigned attrs);
|
PropertyOp getter, StrictPropertyOp setter, unsigned attrs);
|
||||||
typedef JSBool
|
typedef JSBool
|
||||||
(* DefineElementOp)(JSContext *cx, JSObject *obj, uint32_t index, const Value *value,
|
(* DefineElementOp)(JSContext *cx, HandleObject obj, uint32_t index, const Value *value,
|
||||||
PropertyOp getter, StrictPropertyOp setter, unsigned attrs);
|
PropertyOp getter, StrictPropertyOp setter, unsigned attrs);
|
||||||
typedef JSBool
|
typedef JSBool
|
||||||
(* DefineSpecialOp)(JSContext *cx, JSObject *obj, SpecialId sid, const Value *value,
|
(* DefineSpecialOp)(JSContext *cx, HandleObject obj, HandleSpecialId sid, const Value *value,
|
||||||
PropertyOp getter, StrictPropertyOp setter, unsigned attrs);
|
PropertyOp getter, StrictPropertyOp setter, unsigned attrs);
|
||||||
typedef JSBool
|
typedef JSBool
|
||||||
(* GenericIdOp)(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp);
|
(* GenericIdOp)(JSContext *cx, HandleObject obj, HandleObject receiver, HandleId id, Value *vp);
|
||||||
typedef JSBool
|
typedef JSBool
|
||||||
(* PropertyIdOp)(JSContext *cx, JSObject *obj, JSObject *receiver, PropertyName *name, Value *vp);
|
(* PropertyIdOp)(JSContext *cx, HandleObject obj, HandleObject receiver, HandlePropertyName name, Value *vp);
|
||||||
typedef JSBool
|
typedef JSBool
|
||||||
(* ElementIdOp)(JSContext *cx, JSObject *obj, JSObject *receiver, uint32_t index, Value *vp);
|
(* ElementIdOp)(JSContext *cx, HandleObject obj, HandleObject receiver, uint32_t index, Value *vp);
|
||||||
typedef JSBool
|
typedef JSBool
|
||||||
(* ElementIfPresentOp)(JSContext *cx, JSObject *obj, JSObject *receiver, uint32_t index, Value *vp, bool* present);
|
(* ElementIfPresentOp)(JSContext *cx, HandleObject obj, HandleObject receiver, uint32_t index, Value *vp, bool* present);
|
||||||
typedef JSBool
|
typedef JSBool
|
||||||
(* SpecialIdOp)(JSContext *cx, JSObject *obj, JSObject *receiver, SpecialId sid, Value *vp);
|
(* SpecialIdOp)(JSContext *cx, HandleObject obj, HandleObject receiver, HandleSpecialId sid, Value *vp);
|
||||||
typedef JSBool
|
typedef JSBool
|
||||||
(* StrictGenericIdOp)(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict);
|
(* StrictGenericIdOp)(JSContext *cx, HandleObject obj, HandleId id, Value *vp, JSBool strict);
|
||||||
typedef JSBool
|
typedef JSBool
|
||||||
(* StrictPropertyIdOp)(JSContext *cx, JSObject *obj, PropertyName *name, Value *vp, JSBool strict);
|
(* StrictPropertyIdOp)(JSContext *cx, HandleObject obj, HandlePropertyName name, Value *vp, JSBool strict);
|
||||||
typedef JSBool
|
typedef JSBool
|
||||||
(* StrictElementIdOp)(JSContext *cx, JSObject *obj, uint32_t index, Value *vp, JSBool strict);
|
(* StrictElementIdOp)(JSContext *cx, HandleObject obj, uint32_t index, Value *vp, JSBool strict);
|
||||||
typedef JSBool
|
typedef JSBool
|
||||||
(* StrictSpecialIdOp)(JSContext *cx, JSObject *obj, SpecialId sid, Value *vp, JSBool strict);
|
(* StrictSpecialIdOp)(JSContext *cx, HandleObject obj, HandleSpecialId sid, Value *vp, JSBool strict);
|
||||||
typedef JSBool
|
typedef JSBool
|
||||||
(* GenericAttributesOp)(JSContext *cx, JSObject *obj, jsid id, unsigned *attrsp);
|
(* GenericAttributesOp)(JSContext *cx, HandleObject obj, HandleId id, unsigned *attrsp);
|
||||||
typedef JSBool
|
typedef JSBool
|
||||||
(* PropertyAttributesOp)(JSContext *cx, JSObject *obj, PropertyName *name, unsigned *attrsp);
|
(* PropertyAttributesOp)(JSContext *cx, HandleObject obj, HandlePropertyName name, unsigned *attrsp);
|
||||||
typedef JSBool
|
typedef JSBool
|
||||||
(* ElementAttributesOp)(JSContext *cx, JSObject *obj, uint32_t index, unsigned *attrsp);
|
(* ElementAttributesOp)(JSContext *cx, HandleObject obj, uint32_t index, unsigned *attrsp);
|
||||||
typedef JSBool
|
typedef JSBool
|
||||||
(* SpecialAttributesOp)(JSContext *cx, JSObject *obj, SpecialId sid, unsigned *attrsp);
|
(* SpecialAttributesOp)(JSContext *cx, HandleObject obj, HandleSpecialId sid, unsigned *attrsp);
|
||||||
typedef JSBool
|
typedef JSBool
|
||||||
(* DeletePropertyOp)(JSContext *cx, JSObject *obj, PropertyName *name, Value *vp, JSBool strict);
|
(* DeletePropertyOp)(JSContext *cx, HandleObject obj, HandlePropertyName name, Value *vp, JSBool strict);
|
||||||
typedef JSBool
|
typedef JSBool
|
||||||
(* DeleteElementOp)(JSContext *cx, JSObject *obj, uint32_t index, Value *vp, JSBool strict);
|
(* DeleteElementOp)(JSContext *cx, HandleObject obj, uint32_t index, Value *vp, JSBool strict);
|
||||||
typedef JSBool
|
typedef JSBool
|
||||||
(* DeleteSpecialOp)(JSContext *cx, JSObject *obj, SpecialId sid, Value *vp, JSBool strict);
|
(* DeleteSpecialOp)(JSContext *cx, HandleObject obj, HandleSpecialId sid, Value *vp, JSBool strict);
|
||||||
typedef JSType
|
typedef JSType
|
||||||
(* TypeOfOp)(JSContext *cx, JSObject *obj);
|
(* TypeOfOp)(JSContext *cx, HandleObject 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 *
|
typedef JSObject *
|
||||||
(* ObjectOp)(JSContext *cx, JSObject *obj);
|
(* ObjectOp)(JSContext *cx, HandleObject obj);
|
||||||
|
typedef void
|
||||||
|
(* ClearOp)(JSContext *cx, HandleObject obj);
|
||||||
typedef void
|
typedef void
|
||||||
(* FinalizeOp)(FreeOp *fop, JSObject *obj);
|
(* FinalizeOp)(FreeOp *fop, JSObject *obj);
|
||||||
typedef void
|
|
||||||
(* ClearOp)(JSContext *cx, JSObject *obj);
|
|
||||||
|
|
||||||
#define JS_CLASS_MEMBERS \
|
#define JS_CLASS_MEMBERS \
|
||||||
const char *name; \
|
const char *name; \
|
||||||
|
@ -269,8 +231,8 @@ typedef void
|
||||||
/* Optionally non-null members start here. */ \
|
/* Optionally non-null members start here. */ \
|
||||||
JSCheckAccessOp checkAccess; \
|
JSCheckAccessOp checkAccess; \
|
||||||
JSNative call; \
|
JSNative call; \
|
||||||
JSNative construct; \
|
|
||||||
JSHasInstanceOp hasInstance; \
|
JSHasInstanceOp hasInstance; \
|
||||||
|
JSNative construct; \
|
||||||
JSTraceOp trace
|
JSTraceOp trace
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -332,7 +294,6 @@ struct ObjectOps
|
||||||
|
|
||||||
JSNewEnumerateOp enumerate;
|
JSNewEnumerateOp enumerate;
|
||||||
TypeOfOp typeOf;
|
TypeOfOp typeOf;
|
||||||
FixOp fix;
|
|
||||||
ObjectOp thisObject;
|
ObjectOp thisObject;
|
||||||
ClearOp clear;
|
ClearOp clear;
|
||||||
};
|
};
|
||||||
|
@ -340,7 +301,7 @@ struct ObjectOps
|
||||||
#define JS_NULL_OBJECT_OPS \
|
#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,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
|
struct Class
|
||||||
{
|
{
|
||||||
|
@ -406,7 +367,8 @@ Valueify(const JSClass *c)
|
||||||
* value of objects.
|
* value of objects.
|
||||||
*/
|
*/
|
||||||
enum ESClassValue {
|
enum ESClassValue {
|
||||||
ESClass_Array, ESClass_Number, ESClass_String, ESClass_Boolean, ESClass_RegExp
|
ESClass_Array, ESClass_Number, ESClass_String, ESClass_Boolean,
|
||||||
|
ESClass_RegExp, ESClass_ArrayBuffer
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -424,6 +386,25 @@ IsObjectWithClass(const Value &v, ESClassValue classValue, JSContext *cx);
|
||||||
|
|
||||||
} /* namespace js */
|
} /* namespace js */
|
||||||
|
|
||||||
|
namespace JS {
|
||||||
|
|
||||||
|
inline bool
|
||||||
|
IsPoisonedSpecialId(js::SpecialId iden)
|
||||||
|
{
|
||||||
|
if (iden.isObject())
|
||||||
|
return IsPoisonedPtr(iden.toObject());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <> struct RootMethods<js::SpecialId>
|
||||||
|
{
|
||||||
|
static js::SpecialId initial() { return js::SpecialId(); }
|
||||||
|
static ThingRootKind kind() { return THING_ROOT_ID; }
|
||||||
|
static bool poisoned(js::SpecialId id) { return IsPoisonedSpecialId(id); }
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace JS */
|
||||||
|
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
#endif /* jsclass_h__ */
|
#endif /* jsclass_h__ */
|
||||||
|
|
|
@ -1,40 +1,7 @@
|
||||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
/* ***** BEGIN LICENSE BLOCK *****
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
* 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/. */
|
||||||
* 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___
|
#ifndef jsclist_h___
|
||||||
#define jsclist_h___
|
#define jsclist_h___
|
||||||
|
|
|
@ -1,41 +1,8 @@
|
||||||
/* -*- 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 *****
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
* 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/. */
|
||||||
* 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 js_cpucfg___
|
#ifndef js_cpucfg___
|
||||||
#define js_cpucfg___
|
#define js_cpucfg___
|
||||||
|
|
|
@ -1,43 +1,9 @@
|
||||||
/* -*- 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 -*-
|
||||||
* vim: set ts=8 sw=4 et tw=99:
|
* vim: set ts=8 sw=4 et tw=99:
|
||||||
*
|
*
|
||||||
* ***** BEGIN LICENSE BLOCK *****
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
* 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/. */
|
||||||
* 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___
|
#ifndef jsdbgapi_h___
|
||||||
#define jsdbgapi_h___
|
#define jsdbgapi_h___
|
||||||
|
@ -120,6 +86,13 @@ JS_SetRuntimeDebugMode(JSRuntime *rt, JSBool debug);
|
||||||
extern JS_PUBLIC_API(JSBool)
|
extern JS_PUBLIC_API(JSBool)
|
||||||
JS_GetDebugMode(JSContext *cx);
|
JS_GetDebugMode(JSContext *cx);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Turn on/off debugging mode for all compartments. This returns false if any code
|
||||||
|
* from any of the runtime's compartments is running or on the stack.
|
||||||
|
*/
|
||||||
|
JS_FRIEND_API(JSBool)
|
||||||
|
JS_SetDebugModeForAllCompartments(JSContext *cx, JSBool debug);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Turn on/off debugging mode for a single compartment. This should only be
|
* 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
|
* used when no code from this compartment is running or on the stack in any
|
||||||
|
@ -248,6 +221,9 @@ JS_GetFrameAnnotation(JSContext *cx, JSStackFrame *fp);
|
||||||
extern JS_PUBLIC_API(void)
|
extern JS_PUBLIC_API(void)
|
||||||
JS_SetFrameAnnotation(JSContext *cx, JSStackFrame *fp, void *annotation);
|
JS_SetFrameAnnotation(JSContext *cx, JSStackFrame *fp, void *annotation);
|
||||||
|
|
||||||
|
extern JS_PUBLIC_API(JSPrincipals*)
|
||||||
|
JS_GetPrincipalIfDummyFrame(JSContext *cx, JSStackFrame *fpArg);
|
||||||
|
|
||||||
extern JS_PUBLIC_API(JSBool)
|
extern JS_PUBLIC_API(JSBool)
|
||||||
JS_IsScriptFrame(JSContext *cx, JSStackFrame *fp);
|
JS_IsScriptFrame(JSContext *cx, JSStackFrame *fp);
|
||||||
|
|
||||||
|
@ -299,6 +275,17 @@ JS_GetFrameCalleeObject(JSContext *cx, JSStackFrame *fp);
|
||||||
|
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is almost JS_GetClass(obj)->name except that certain debug-only
|
||||||
|
* proxies are made transparent. In particular, this function turns the class
|
||||||
|
* of any scope (returned via JS_GetFrameScopeChain or JS_GetFrameCalleeObject)
|
||||||
|
* from "Proxy" to "Call", "Block", "With" etc.
|
||||||
|
*/
|
||||||
|
extern JS_PUBLIC_API(const char *)
|
||||||
|
JS_GetDebugClassName(JSObject *obj);
|
||||||
|
|
||||||
|
/************************************************************************/
|
||||||
|
|
||||||
extern JS_PUBLIC_API(const char *)
|
extern JS_PUBLIC_API(const char *)
|
||||||
JS_GetScriptFilename(JSContext *cx, JSScript *script);
|
JS_GetScriptFilename(JSContext *cx, JSScript *script);
|
||||||
|
|
||||||
|
@ -352,7 +339,6 @@ typedef struct JSPropertyDesc {
|
||||||
jsval value; /* property value */
|
jsval value; /* property value */
|
||||||
uint8_t flags; /* flags, see below */
|
uint8_t flags; /* flags, see below */
|
||||||
uint8_t spare; /* unused */
|
uint8_t spare; /* unused */
|
||||||
uint16_t slot; /* argument/variable slot */
|
|
||||||
jsval alias; /* alias id if JSPD_ALIAS flag */
|
jsval alias; /* alias id if JSPD_ALIAS flag */
|
||||||
} JSPropertyDesc;
|
} JSPropertyDesc;
|
||||||
|
|
||||||
|
@ -360,8 +346,6 @@ typedef struct JSPropertyDesc {
|
||||||
#define JSPD_READONLY 0x02 /* assignment is error */
|
#define JSPD_READONLY 0x02 /* assignment is error */
|
||||||
#define JSPD_PERMANENT 0x04 /* property cannot be deleted */
|
#define JSPD_PERMANENT 0x04 /* property cannot be deleted */
|
||||||
#define JSPD_ALIAS 0x08 /* property has an alias id */
|
#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, */
|
#define JSPD_EXCEPTION 0x40 /* exception occurred fetching the property, */
|
||||||
/* value is exception */
|
/* value is exception */
|
||||||
#define JSPD_ERROR 0x80 /* native getter returned JS_FALSE without */
|
#define JSPD_ERROR 0x80 /* native getter returned JS_FALSE without */
|
||||||
|
@ -374,13 +358,6 @@ typedef struct JSPropertyDescArray {
|
||||||
|
|
||||||
typedef struct JSScopeProperty JSScopeProperty;
|
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)
|
extern JS_PUBLIC_API(JSBool)
|
||||||
JS_GetPropertyDescArray(JSContext *cx, JSObject *obj, JSPropertyDescArray *pda);
|
JS_GetPropertyDescArray(JSContext *cx, JSObject *obj, JSPropertyDescArray *pda);
|
||||||
|
|
||||||
|
@ -418,23 +395,6 @@ JS_GetFunctionTotalSize(JSContext *cx, JSFunction *fun);
|
||||||
extern JS_PUBLIC_API(size_t)
|
extern JS_PUBLIC_API(size_t)
|
||||||
JS_GetScriptTotalSize(JSContext *cx, JSScript *script);
|
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)
|
extern JS_FRIEND_API(void)
|
||||||
|
@ -532,6 +492,16 @@ js_ResumeVtune();
|
||||||
|
|
||||||
#endif /* MOZ_VTUNE */
|
#endif /* MOZ_VTUNE */
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
|
||||||
|
extern JS_FRIEND_API(JSBool)
|
||||||
|
js_StartPerf();
|
||||||
|
|
||||||
|
extern JS_FRIEND_API(JSBool)
|
||||||
|
js_StopPerf();
|
||||||
|
|
||||||
|
#endif /* __linux__ */
|
||||||
|
|
||||||
extern JS_PUBLIC_API(void)
|
extern JS_PUBLIC_API(void)
|
||||||
JS_DumpBytecode(JSContext *cx, JSScript *script);
|
JS_DumpBytecode(JSContext *cx, JSScript *script);
|
||||||
|
|
||||||
|
@ -547,6 +517,9 @@ JS_DumpCompartmentPCCounts(JSContext *cx);
|
||||||
extern JS_PUBLIC_API(JSObject *)
|
extern JS_PUBLIC_API(JSObject *)
|
||||||
JS_UnwrapObject(JSObject *obj);
|
JS_UnwrapObject(JSObject *obj);
|
||||||
|
|
||||||
|
extern JS_PUBLIC_API(JSObject *)
|
||||||
|
JS_UnwrapObjectAndInnerize(JSObject *obj);
|
||||||
|
|
||||||
/* Call the context debug handler on the topmost scripted frame. */
|
/* Call the context debug handler on the topmost scripted frame. */
|
||||||
extern JS_FRIEND_API(JSBool)
|
extern JS_FRIEND_API(JSBool)
|
||||||
js_CallContextDebugHandler(JSContext *cx);
|
js_CallContextDebugHandler(JSContext *cx);
|
||||||
|
|
|
@ -1,40 +1,7 @@
|
||||||
/* -*- 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 *****
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
* 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/. */
|
||||||
* 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___
|
#ifndef jsdhash_h___
|
||||||
#define jsdhash_h___
|
#define jsdhash_h___
|
||||||
|
|
|
@ -1,41 +1,8 @@
|
||||||
/* -*- 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 *****
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
* 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/. */
|
||||||
* 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):
|
|
||||||
*
|
|
||||||
* 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 jsfriendapi_h___
|
#ifndef jsfriendapi_h___
|
||||||
#define jsfriendapi_h___
|
#define jsfriendapi_h___
|
||||||
|
@ -87,6 +54,15 @@ JS_GetCustomIteratorCount(JSContext *cx);
|
||||||
extern JS_FRIEND_API(JSBool)
|
extern JS_FRIEND_API(JSBool)
|
||||||
JS_NondeterministicGetWeakMapKeys(JSContext *cx, JSObject *obj, JSObject **ret);
|
JS_NondeterministicGetWeakMapKeys(JSContext *cx, JSObject *obj, JSObject **ret);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Determine whether the given object is backed by a DeadObjectProxy.
|
||||||
|
*
|
||||||
|
* Such objects hold no other objects (they have no outgoing reference edges)
|
||||||
|
* and will throw if you touch them (e.g. by reading/writing a property).
|
||||||
|
*/
|
||||||
|
extern JS_FRIEND_API(JSBool)
|
||||||
|
JS_IsDeadWrapper(JSObject *obj);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Used by the cycle collector to trace through the shape and all
|
* Used by the cycle collector to trace through the shape and all
|
||||||
* shapes it reaches, marking all non-shape children found in the
|
* shapes it reaches, marking all non-shape children found in the
|
||||||
|
@ -117,6 +93,9 @@ JS_SetAccumulateTelemetryCallback(JSRuntime *rt, JSAccumulateTelemetryDataCallba
|
||||||
extern JS_FRIEND_API(JSPrincipals *)
|
extern JS_FRIEND_API(JSPrincipals *)
|
||||||
JS_GetCompartmentPrincipals(JSCompartment *compartment);
|
JS_GetCompartmentPrincipals(JSCompartment *compartment);
|
||||||
|
|
||||||
|
extern JS_FRIEND_API(void)
|
||||||
|
JS_SetCompartmentPrincipals(JSCompartment *compartment, JSPrincipals *principals);
|
||||||
|
|
||||||
/* Safe to call with input obj == NULL. Returns non-NULL iff obj != NULL. */
|
/* Safe to call with input obj == NULL. Returns non-NULL iff obj != NULL. */
|
||||||
extern JS_FRIEND_API(JSObject *)
|
extern JS_FRIEND_API(JSObject *)
|
||||||
JS_ObjectToInnerObject(JSContext *cx, JSObject *obj);
|
JS_ObjectToInnerObject(JSContext *cx, JSObject *obj);
|
||||||
|
@ -129,7 +108,7 @@ extern JS_FRIEND_API(JSObject *)
|
||||||
JS_CloneObject(JSContext *cx, JSObject *obj, JSObject *proto, JSObject *parent);
|
JS_CloneObject(JSContext *cx, JSObject *obj, JSObject *proto, JSObject *parent);
|
||||||
|
|
||||||
extern JS_FRIEND_API(JSBool)
|
extern JS_FRIEND_API(JSBool)
|
||||||
js_GetterOnlyPropertyStub(JSContext *cx, JSObject *obj, jsid id, JSBool strict, jsval *vp);
|
js_GetterOnlyPropertyStub(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict, jsval *vp);
|
||||||
|
|
||||||
JS_FRIEND_API(void)
|
JS_FRIEND_API(void)
|
||||||
js_ReportOverRecursed(JSContext *maybecx);
|
js_ReportOverRecursed(JSContext *maybecx);
|
||||||
|
@ -164,7 +143,10 @@ extern JS_FRIEND_API(JSBool)
|
||||||
JS_WrapPropertyDescriptor(JSContext *cx, js::PropertyDescriptor *desc);
|
JS_WrapPropertyDescriptor(JSContext *cx, js::PropertyDescriptor *desc);
|
||||||
|
|
||||||
extern JS_FRIEND_API(JSBool)
|
extern JS_FRIEND_API(JSBool)
|
||||||
JS_EnumerateState(JSContext *cx, JSObject *obj, JSIterateOp enum_op, js::Value *statep, jsid *idp);
|
JS_WrapAutoIdVector(JSContext *cx, JS::AutoIdVector &props);
|
||||||
|
|
||||||
|
extern JS_FRIEND_API(JSBool)
|
||||||
|
JS_EnumerateState(JSContext *cx, JSHandleObject obj, JSIterateOp enum_op, js::Value *statep, jsid *idp);
|
||||||
|
|
||||||
struct JSFunctionSpecWithHelp {
|
struct JSFunctionSpecWithHelp {
|
||||||
const char *name;
|
const char *name;
|
||||||
|
@ -217,26 +199,13 @@ GetRuntime(const JSContext *cx)
|
||||||
typedef bool
|
typedef bool
|
||||||
(* PreserveWrapperCallback)(JSContext *cx, JSObject *obj);
|
(* PreserveWrapperCallback)(JSContext *cx, JSObject *obj);
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
/*
|
/*
|
||||||
* DEBUG-only method to dump the complete object graph of heap-allocated things.
|
* Dump the complete object graph of heap-allocated things.
|
||||||
* fp is the file for the dump output.
|
* fp is the file for the dump output.
|
||||||
*/
|
*/
|
||||||
extern JS_FRIEND_API(void)
|
extern JS_FRIEND_API(void)
|
||||||
DumpHeapComplete(JSRuntime *rt, FILE *fp);
|
DumpHeapComplete(JSRuntime *rt, FILE *fp);
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
class JS_FRIEND_API(AutoPreserveCompartment) {
|
|
||||||
private:
|
|
||||||
JSContext *cx;
|
|
||||||
JSCompartment *oldCompartment;
|
|
||||||
public:
|
|
||||||
AutoPreserveCompartment(JSContext *cx JS_GUARD_OBJECT_NOTIFIER_PARAM);
|
|
||||||
~AutoPreserveCompartment();
|
|
||||||
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
|
|
||||||
};
|
|
||||||
|
|
||||||
class JS_FRIEND_API(AutoSwitchCompartment) {
|
class JS_FRIEND_API(AutoSwitchCompartment) {
|
||||||
private:
|
private:
|
||||||
JSContext *cx;
|
JSContext *cx;
|
||||||
|
@ -296,6 +265,15 @@ TraceWeakMaps(WeakMapTracer *trc);
|
||||||
extern JS_FRIEND_API(bool)
|
extern JS_FRIEND_API(bool)
|
||||||
GCThingIsMarkedGray(void *thing);
|
GCThingIsMarkedGray(void *thing);
|
||||||
|
|
||||||
|
extern JS_FRIEND_API(JSCompartment*)
|
||||||
|
GetGCThingCompartment(void *thing);
|
||||||
|
|
||||||
|
typedef void
|
||||||
|
(GCThingCallback)(void *closure, void *gcthing);
|
||||||
|
|
||||||
|
extern JS_FRIEND_API(void)
|
||||||
|
VisitGrayWrapperTargets(JSCompartment *comp, GCThingCallback *callback, void *closure);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Shadow declarations of JS internal structures, for access by inline access
|
* Shadow declarations of JS internal structures, for access by inline access
|
||||||
* functions below. Do not use these structures in any other way. When adding
|
* functions below. Do not use these structures in any other way. When adding
|
||||||
|
@ -388,6 +366,9 @@ GetObjectParentMaybeScope(JSObject *obj);
|
||||||
JS_FRIEND_API(JSObject *)
|
JS_FRIEND_API(JSObject *)
|
||||||
GetGlobalForObjectCrossCompartment(JSObject *obj);
|
GetGlobalForObjectCrossCompartment(JSObject *obj);
|
||||||
|
|
||||||
|
JS_FRIEND_API(void)
|
||||||
|
NotifyAnimationActivity(JSObject *obj);
|
||||||
|
|
||||||
JS_FRIEND_API(bool)
|
JS_FRIEND_API(bool)
|
||||||
IsOriginalScriptFunction(JSFunction *fun);
|
IsOriginalScriptFunction(JSFunction *fun);
|
||||||
|
|
||||||
|
@ -498,6 +479,9 @@ CastAsJSStrictPropertyOp(JSObject *object)
|
||||||
JS_FRIEND_API(bool)
|
JS_FRIEND_API(bool)
|
||||||
GetPropertyNames(JSContext *cx, JSObject *obj, unsigned flags, js::AutoIdVector *props);
|
GetPropertyNames(JSContext *cx, JSObject *obj, unsigned flags, js::AutoIdVector *props);
|
||||||
|
|
||||||
|
JS_FRIEND_API(bool)
|
||||||
|
GetGeneric(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp);
|
||||||
|
|
||||||
JS_FRIEND_API(bool)
|
JS_FRIEND_API(bool)
|
||||||
StringIsArrayIndex(JSLinearString *str, uint32_t *indexp);
|
StringIsArrayIndex(JSLinearString *str, uint32_t *indexp);
|
||||||
|
|
||||||
|
@ -552,6 +536,34 @@ GetPCCountScriptSummary(JSContext *cx, size_t script);
|
||||||
JS_FRIEND_API(JSString *)
|
JS_FRIEND_API(JSString *)
|
||||||
GetPCCountScriptContents(JSContext *cx, size_t script);
|
GetPCCountScriptContents(JSContext *cx, size_t script);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A call stack can be specified to the JS engine such that all JS entry/exits
|
||||||
|
* to functions push/pop an entry to/from the specified stack.
|
||||||
|
*
|
||||||
|
* For more detailed information, see vm/SPSProfiler.h
|
||||||
|
*/
|
||||||
|
struct ProfileEntry {
|
||||||
|
/*
|
||||||
|
* These two fields are marked as 'volatile' so that the compiler doesn't
|
||||||
|
* re-order instructions which modify them. The operation in question is:
|
||||||
|
*
|
||||||
|
* stack[i].string = str;
|
||||||
|
* (*size)++;
|
||||||
|
*
|
||||||
|
* If the size increment were re-ordered before the store of the string,
|
||||||
|
* then if sampling occurred there would be a bogus entry on the stack.
|
||||||
|
*/
|
||||||
|
const char * volatile string;
|
||||||
|
void * volatile sp;
|
||||||
|
};
|
||||||
|
|
||||||
|
JS_FRIEND_API(void)
|
||||||
|
SetRuntimeProfilingStack(JSRuntime *rt, ProfileEntry *stack, uint32_t *size,
|
||||||
|
uint32_t max);
|
||||||
|
|
||||||
|
JS_FRIEND_API(void)
|
||||||
|
EnableRuntimeProfilingStack(JSRuntime *rt, bool enabled);
|
||||||
|
|
||||||
#ifdef JS_THREADSAFE
|
#ifdef JS_THREADSAFE
|
||||||
JS_FRIEND_API(void *)
|
JS_FRIEND_API(void *)
|
||||||
GetOwnerThread(const JSContext *cx);
|
GetOwnerThread(const JSContext *cx);
|
||||||
|
@ -581,7 +593,7 @@ extern JS_FRIEND_API(const JSStructuredCloneCallbacks *)
|
||||||
GetContextStructuredCloneCallbacks(JSContext *cx);
|
GetContextStructuredCloneCallbacks(JSContext *cx);
|
||||||
|
|
||||||
extern JS_FRIEND_API(JSVersion)
|
extern JS_FRIEND_API(JSVersion)
|
||||||
VersionSetXML(JSVersion version, bool enable);
|
VersionSetMoarXML(JSVersion version, bool enable);
|
||||||
|
|
||||||
extern JS_FRIEND_API(bool)
|
extern JS_FRIEND_API(bool)
|
||||||
CanCallContextDebugHandler(JSContext *cx);
|
CanCallContextDebugHandler(JSContext *cx);
|
||||||
|
@ -610,8 +622,8 @@ SizeOfJSContext();
|
||||||
D(TOO_MUCH_MALLOC) \
|
D(TOO_MUCH_MALLOC) \
|
||||||
D(ALLOC_TRIGGER) \
|
D(ALLOC_TRIGGER) \
|
||||||
D(DEBUG_GC) \
|
D(DEBUG_GC) \
|
||||||
D(UNUSED2) /* was SHAPE */ \
|
D(DEBUG_MODE_GC) \
|
||||||
D(UNUSED3) /* was REFILL */ \
|
D(TRANSPLANT) \
|
||||||
\
|
\
|
||||||
/* Reasons from Firefox */ \
|
/* Reasons from Firefox */ \
|
||||||
D(DOM_WINDOW_UTILS) \
|
D(DOM_WINDOW_UTILS) \
|
||||||
|
@ -629,7 +641,9 @@ SizeOfJSContext();
|
||||||
D(DOM_IPC) \
|
D(DOM_IPC) \
|
||||||
D(DOM_WORKER) \
|
D(DOM_WORKER) \
|
||||||
D(INTER_SLICE_GC) \
|
D(INTER_SLICE_GC) \
|
||||||
D(REFRESH_FRAME)
|
D(REFRESH_FRAME) \
|
||||||
|
D(FULL_GC_TIMER) \
|
||||||
|
D(SHUTDOWN_CC)
|
||||||
|
|
||||||
namespace gcreason {
|
namespace gcreason {
|
||||||
|
|
||||||
|
@ -639,7 +653,15 @@ enum Reason {
|
||||||
GCREASONS(MAKE_REASON)
|
GCREASONS(MAKE_REASON)
|
||||||
#undef MAKE_REASON
|
#undef MAKE_REASON
|
||||||
NO_REASON,
|
NO_REASON,
|
||||||
NUM_REASONS
|
NUM_REASONS,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* For telemetry, we want to keep a fixed max bucket size over time so we
|
||||||
|
* don't have to switch histograms. 100 is conservative; as of this writing
|
||||||
|
* there are 26. But the cost of extra buckets seems to be low while the
|
||||||
|
* cost of switching histograms is high.
|
||||||
|
*/
|
||||||
|
NUM_TELEMETRY_REASONS = 100
|
||||||
};
|
};
|
||||||
|
|
||||||
} /* namespace gcreason */
|
} /* namespace gcreason */
|
||||||
|
@ -650,6 +672,15 @@ PrepareCompartmentForGC(JSCompartment *comp);
|
||||||
extern JS_FRIEND_API(void)
|
extern JS_FRIEND_API(void)
|
||||||
PrepareForFullGC(JSRuntime *rt);
|
PrepareForFullGC(JSRuntime *rt);
|
||||||
|
|
||||||
|
extern JS_FRIEND_API(void)
|
||||||
|
PrepareForIncrementalGC(JSRuntime *rt);
|
||||||
|
|
||||||
|
extern JS_FRIEND_API(bool)
|
||||||
|
IsGCScheduled(JSRuntime *rt);
|
||||||
|
|
||||||
|
extern JS_FRIEND_API(void)
|
||||||
|
SkipCompartmentForGC(JSCompartment *comp);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* When triggering a GC using one of the functions below, it is first necessary
|
* When triggering a GC using one of the functions below, it is first necessary
|
||||||
* to select the compartments to be collected. To do this, you can call
|
* to select the compartments to be collected. To do this, you can call
|
||||||
|
@ -667,7 +698,7 @@ extern JS_FRIEND_API(void)
|
||||||
IncrementalGC(JSRuntime *rt, gcreason::Reason reason);
|
IncrementalGC(JSRuntime *rt, gcreason::Reason reason);
|
||||||
|
|
||||||
extern JS_FRIEND_API(void)
|
extern JS_FRIEND_API(void)
|
||||||
SetGCSliceTimeBudget(JSContext *cx, int64_t millis);
|
FinishIncrementalGC(JSRuntime *rt, gcreason::Reason reason);
|
||||||
|
|
||||||
enum GCProgress {
|
enum GCProgress {
|
||||||
/*
|
/*
|
||||||
|
@ -724,12 +755,18 @@ IsIncrementalBarrierNeeded(JSContext *cx);
|
||||||
extern JS_FRIEND_API(bool)
|
extern JS_FRIEND_API(bool)
|
||||||
IsIncrementalBarrierNeededOnObject(JSObject *obj);
|
IsIncrementalBarrierNeededOnObject(JSObject *obj);
|
||||||
|
|
||||||
|
extern JS_FRIEND_API(bool)
|
||||||
|
IsIncrementalBarrierNeededOnScript(JSScript *obj);
|
||||||
|
|
||||||
extern JS_FRIEND_API(void)
|
extern JS_FRIEND_API(void)
|
||||||
IncrementalReferenceBarrier(void *ptr);
|
IncrementalReferenceBarrier(void *ptr);
|
||||||
|
|
||||||
extern JS_FRIEND_API(void)
|
extern JS_FRIEND_API(void)
|
||||||
IncrementalValueBarrier(const Value &v);
|
IncrementalValueBarrier(const Value &v);
|
||||||
|
|
||||||
|
extern JS_FRIEND_API(void)
|
||||||
|
PokeGC(JSRuntime *rt);
|
||||||
|
|
||||||
class ObjectPtr
|
class ObjectPtr
|
||||||
{
|
{
|
||||||
JSObject *value;
|
JSObject *value;
|
||||||
|
@ -790,6 +827,16 @@ CastToJSFreeOp(FreeOp *fop)
|
||||||
extern JS_FRIEND_API(const jschar*)
|
extern JS_FRIEND_API(const jschar*)
|
||||||
GetErrorTypeNameFromNumber(JSContext* cx, const unsigned errorNumber);
|
GetErrorTypeNameFromNumber(JSContext* cx, const unsigned errorNumber);
|
||||||
|
|
||||||
|
/* Implemented in jswrapper.cpp. */
|
||||||
|
typedef enum NukedGlobalHandling {
|
||||||
|
NukeForGlobalObject,
|
||||||
|
DontNukeForGlobalObject
|
||||||
|
} NukedGlobalHandling;
|
||||||
|
|
||||||
|
extern JS_FRIEND_API(JSBool)
|
||||||
|
NukeChromeCrossCompartmentWrappersForGlobal(JSContext *cx, JSObject *obj,
|
||||||
|
NukedGlobalHandling nukeGlobal);
|
||||||
|
|
||||||
} /* namespace js */
|
} /* namespace js */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -963,6 +1010,16 @@ JS_NewArrayBuffer(JSContext *cx, uint32_t nbytes);
|
||||||
extern JS_FRIEND_API(JSBool)
|
extern JS_FRIEND_API(JSBool)
|
||||||
JS_IsTypedArrayObject(JSObject *obj, JSContext *cx);
|
JS_IsTypedArrayObject(JSObject *obj, JSContext *cx);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check whether obj supports JS_GetArrayBufferView* APIs. Note that this may
|
||||||
|
* return false if a security wrapper is encountered that denies the
|
||||||
|
* unwrapping. If this test or one of the more specific tests succeeds, then it
|
||||||
|
* is safe to call the various ArrayBufferView accessor JSAPI calls defined
|
||||||
|
* below. cx MUST be non-NULL and valid.
|
||||||
|
*/
|
||||||
|
extern JS_FRIEND_API(JSBool)
|
||||||
|
JS_IsArrayBufferViewObject(JSObject *obj, JSContext *cx);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Test for specific typed array types (ArrayBufferView subtypes)
|
* Test for specific typed array types (ArrayBufferView subtypes)
|
||||||
*/
|
*/
|
||||||
|
@ -1063,6 +1120,14 @@ JS_GetTypedArrayByteOffset(JSObject *obj, JSContext *cx);
|
||||||
extern JS_FRIEND_API(uint32_t)
|
extern JS_FRIEND_API(uint32_t)
|
||||||
JS_GetTypedArrayByteLength(JSObject *obj, JSContext *cx);
|
JS_GetTypedArrayByteLength(JSObject *obj, JSContext *cx);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check whether obj supports JS_ArrayBufferView* APIs. Note that this may
|
||||||
|
* return false if a security wrapper is encountered that denies the
|
||||||
|
* unwrapping.
|
||||||
|
*/
|
||||||
|
extern JS_FRIEND_API(JSBool)
|
||||||
|
JS_IsArrayBufferViewObject(JSObject *obj, JSContext *cx);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* More generic name for JS_GetTypedArrayByteLength to cover DataViews as well
|
* More generic name for JS_GetTypedArrayByteLength to cover DataViews as well
|
||||||
*/
|
*/
|
||||||
|
@ -1106,4 +1171,46 @@ JS_GetFloat64ArrayData(JSObject *obj, JSContext *cx);
|
||||||
extern JS_FRIEND_API(void *)
|
extern JS_FRIEND_API(void *)
|
||||||
JS_GetArrayBufferViewData(JSObject *obj, JSContext *cx);
|
JS_GetArrayBufferViewData(JSObject *obj, JSContext *cx);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check whether obj supports JS_GetDataView* APIs. Note that this may fail and
|
||||||
|
* throw an exception if a security wrapper is encountered that denies the
|
||||||
|
* operation.
|
||||||
|
*/
|
||||||
|
JS_FRIEND_API(JSBool)
|
||||||
|
JS_IsDataViewObject(JSContext *cx, JSObject *obj, JSBool *isDataView);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return the byte offset of a data view into its array buffer. |obj| must be a
|
||||||
|
* DataView.
|
||||||
|
*
|
||||||
|
* |obj| must have passed a JS_IsDataViewObject test, or somehow be known that
|
||||||
|
* it would pass such a test: it is a data view or a wrapper of a data view,
|
||||||
|
* and the unwrapping will succeed. If cx is NULL, then DEBUG builds may be
|
||||||
|
* unable to assert when unwrapping should be disallowed.
|
||||||
|
*/
|
||||||
|
JS_FRIEND_API(uint32_t)
|
||||||
|
JS_GetDataViewByteOffset(JSObject *obj, JSContext *cx);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return the byte length of a data view.
|
||||||
|
*
|
||||||
|
* |obj| must have passed a JS_IsDataViewObject test, or somehow be known that
|
||||||
|
* it would pass such a test: it is a data view or a wrapper of a data view,
|
||||||
|
* and the unwrapping will succeed. If cx is NULL, then DEBUG builds may be
|
||||||
|
* unable to assert when unwrapping should be disallowed.
|
||||||
|
*/
|
||||||
|
JS_FRIEND_API(uint32_t)
|
||||||
|
JS_GetDataViewByteLength(JSObject *obj, JSContext *cx);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return a pointer to the beginning of the data referenced by a DataView.
|
||||||
|
*
|
||||||
|
* |obj| must have passed a JS_IsDataViewObject test, or somehow be known that
|
||||||
|
* it would pass such a test: it is a data view or a wrapper of a data view,
|
||||||
|
* and the unwrapping will succeed. If cx is NULL, then DEBUG builds may be
|
||||||
|
* unable to assert when unwrapping should be disallowed.
|
||||||
|
*/
|
||||||
|
JS_FRIEND_API(void *)
|
||||||
|
JS_GetDataViewData(JSObject *obj, JSContext *cx);
|
||||||
|
|
||||||
#endif /* jsfriendapi_h___ */
|
#endif /* jsfriendapi_h___ */
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,41 +1,8 @@
|
||||||
/* -*- 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 *****
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
* 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/. */
|
||||||
* 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___
|
#ifndef jshash_h___
|
||||||
#define jshash_h___
|
#define jshash_h___
|
||||||
|
|
|
@ -1,41 +1,8 @@
|
||||||
/* -*- 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 *****
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
* 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/. */
|
||||||
* 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__
|
#ifndef jslock_h__
|
||||||
#define jslock_h__
|
#define jslock_h__
|
||||||
|
|
||||||
|
@ -56,6 +23,10 @@
|
||||||
|
|
||||||
#else /* JS_THREADSAFE */
|
#else /* JS_THREADSAFE */
|
||||||
|
|
||||||
|
typedef struct PRThread PRThread;
|
||||||
|
typedef struct PRCondVar PRCondVar;
|
||||||
|
typedef struct PRLock PRLock;
|
||||||
|
|
||||||
# define JS_ATOMIC_INCREMENT(p) (++*(p))
|
# define JS_ATOMIC_INCREMENT(p) (++*(p))
|
||||||
# define JS_ATOMIC_DECREMENT(p) (--*(p))
|
# define JS_ATOMIC_DECREMENT(p) (--*(p))
|
||||||
# define JS_ATOMIC_ADD(p,v) (*(p) += (v))
|
# define JS_ATOMIC_ADD(p,v) (*(p) += (v))
|
||||||
|
|
|
@ -1,39 +1,6 @@
|
||||||
/* ***** BEGIN LICENSE BLOCK *****
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
* 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/. */
|
||||||
* 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 JSON.
|
|
||||||
*
|
|
||||||
* The Initial Developer of the Original Code is
|
|
||||||
* 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"),
|
|
||||||
* 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 json_h___
|
#ifndef json_h___
|
||||||
#define json_h___
|
#define json_h___
|
||||||
|
@ -50,9 +17,14 @@ extern JSObject *
|
||||||
js_InitJSONClass(JSContext *cx, JSObject *obj);
|
js_InitJSONClass(JSContext *cx, JSObject *obj);
|
||||||
|
|
||||||
extern JSBool
|
extern JSBool
|
||||||
js_Stringify(JSContext *cx, js::Value *vp, JSObject *replacer, js::Value space,
|
js_Stringify(JSContext *cx, js::MutableHandleValue vp,
|
||||||
|
JSObject *replacer, js::Value space,
|
||||||
js::StringBuffer &sb);
|
js::StringBuffer &sb);
|
||||||
|
|
||||||
|
// Avoid build errors on certain platforms that define these names as constants
|
||||||
|
#undef STRICT
|
||||||
|
#undef LEGACY
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The type of JSON decoding to perform. Strict decoding is to-the-spec;
|
* 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
|
* legacy decoding accepts a few non-JSON syntaxes historically accepted by the
|
||||||
|
|
|
@ -1,40 +1,7 @@
|
||||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||||
/* ***** BEGIN LICENSE BLOCK *****
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
* 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/. */
|
||||||
* 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___
|
#ifndef jsperf_h___
|
||||||
#define jsperf_h___
|
#define jsperf_h___
|
||||||
|
|
|
@ -1,40 +1,7 @@
|
||||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
/* ***** BEGIN LICENSE BLOCK *****
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
* 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/. */
|
||||||
* 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___
|
#ifndef jsprf_h___
|
||||||
#define jsprf_h___
|
#define jsprf_h___
|
||||||
|
|
|
@ -1,40 +1,9 @@
|
||||||
/* -*- 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 -*-
|
||||||
* vim: set sw=4 ts=8 et tw=80 ft=c:
|
* vim: set sw=4 ts=8 et tw=80 ft=c:
|
||||||
*
|
*
|
||||||
* ***** BEGIN LICENSE BLOCK *****
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
* 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/. */
|
||||||
* 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 1.7 work in progress, released
|
|
||||||
* February 14, 2006.
|
|
||||||
*
|
|
||||||
* The Initial Developer of the Original Code is
|
|
||||||
* Brendan Eich <brendan@mozilla.org>
|
|
||||||
*
|
|
||||||
* 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 ***** */
|
|
||||||
|
|
||||||
#include "jsversion.h"
|
#include "jsversion.h"
|
||||||
|
|
||||||
|
@ -94,6 +63,7 @@ JS_PROTO(AnyName, 35, js_InitNullClass)
|
||||||
JS_PROTO(WeakMap, 36, js_InitWeakMapClass)
|
JS_PROTO(WeakMap, 36, js_InitWeakMapClass)
|
||||||
JS_PROTO(Map, 37, js_InitMapClass)
|
JS_PROTO(Map, 37, js_InitMapClass)
|
||||||
JS_PROTO(Set, 38, js_InitSetClass)
|
JS_PROTO(Set, 38, js_InitSetClass)
|
||||||
|
JS_PROTO(DataView, 39, js_InitTypedArrayClasses)
|
||||||
|
|
||||||
#undef XML_INIT
|
#undef XML_INIT
|
||||||
#undef NAMESPACE_INIT
|
#undef NAMESPACE_INIT
|
||||||
|
|
|
@ -1,43 +1,9 @@
|
||||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||||
* vim: set ts=4 sw=4 et tw=99:
|
* vim: set ts=4 sw=4 et tw=99:
|
||||||
*
|
*
|
||||||
* ***** BEGIN LICENSE BLOCK *****
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
* 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/. */
|
||||||
* 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___
|
#ifndef jsproxy_h___
|
||||||
#define jsproxy_h___
|
#define jsproxy_h___
|
||||||
|
@ -47,33 +13,91 @@
|
||||||
|
|
||||||
namespace js {
|
namespace js {
|
||||||
|
|
||||||
/* Base class for all C++ proxy handlers. */
|
class Wrapper;
|
||||||
class JS_FRIEND_API(ProxyHandler) {
|
|
||||||
|
/*
|
||||||
|
* A proxy is a JSObject that implements generic behavior by providing custom
|
||||||
|
* implementations for each object trap. The implementation for each trap is
|
||||||
|
* provided by a C++ object stored on the proxy, known as its handler.
|
||||||
|
*
|
||||||
|
* A major use case for proxies is to forward each trap to another object,
|
||||||
|
* known as its target. The target can be an arbitrary C++ object. Not every
|
||||||
|
* proxy has the notion of a target, however.
|
||||||
|
*
|
||||||
|
* Proxy traps are grouped into fundamental and derived traps. Every proxy has
|
||||||
|
* to at least provide implementations for the fundamental traps, but the
|
||||||
|
* derived traps can be implemented in terms of the fundamental ones.
|
||||||
|
*
|
||||||
|
* To minimize code duplication, a set of abstract proxy handler classes is
|
||||||
|
* provided, from which other handlers may inherit. These abstract classes
|
||||||
|
* are organized in the following hierarchy:
|
||||||
|
*
|
||||||
|
* BaseProxyHandler
|
||||||
|
* |
|
||||||
|
* IndirectProxyHandler
|
||||||
|
* |
|
||||||
|
* DirectProxyHandler
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* BaseProxyHandler is the most generic kind of proxy handler. It does not make
|
||||||
|
* any assumptions about the target. Consequently, it does not provide any
|
||||||
|
* default implementation for the fundamental traps. It does, however, implement
|
||||||
|
* the derived traps in terms of the fundamental ones. This allows consumers of
|
||||||
|
* this class to define any custom behavior they want.
|
||||||
|
*/
|
||||||
|
class JS_FRIEND_API(BaseProxyHandler) {
|
||||||
void *mFamily;
|
void *mFamily;
|
||||||
public:
|
public:
|
||||||
explicit ProxyHandler(void *family);
|
explicit BaseProxyHandler(void *family);
|
||||||
virtual ~ProxyHandler();
|
virtual ~BaseProxyHandler();
|
||||||
|
|
||||||
|
inline void *family() {
|
||||||
|
return mFamily;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool isOuterWindow() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The function Wrapper::wrapperHandler takes a pointer to a
|
||||||
|
* BaseProxyHandler and returns a pointer to a Wrapper if and only if the
|
||||||
|
* BaseProxyHandler is a wrapper handler (otherwise, it returns NULL).
|
||||||
|
*
|
||||||
|
* Unfortunately, we can't inherit Wrapper from BaseProxyHandler, since that
|
||||||
|
* would create a dreaded diamond, and we can't use dynamic_cast to cast
|
||||||
|
* BaseProxyHandler to Wrapper, since that would require us to compile with
|
||||||
|
* run-time type information. Hence the need for this virtual function.
|
||||||
|
*/
|
||||||
|
virtual Wrapper *toWrapper() {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* ES5 Harmony fundamental proxy traps. */
|
/* ES5 Harmony fundamental proxy traps. */
|
||||||
virtual bool getPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id, bool set,
|
virtual bool getPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id,
|
||||||
PropertyDescriptor *desc) = 0;
|
bool set, PropertyDescriptor *desc) = 0;
|
||||||
virtual bool getOwnPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id, bool set,
|
virtual bool getOwnPropertyDescriptor(JSContext *cx, JSObject *proxy,
|
||||||
|
jsid id, bool set,
|
||||||
PropertyDescriptor *desc) = 0;
|
PropertyDescriptor *desc) = 0;
|
||||||
virtual bool defineProperty(JSContext *cx, JSObject *proxy, jsid id,
|
virtual bool defineProperty(JSContext *cx, JSObject *proxy, jsid id,
|
||||||
PropertyDescriptor *desc) = 0;
|
PropertyDescriptor *desc) = 0;
|
||||||
virtual bool getOwnPropertyNames(JSContext *cx, JSObject *proxy, AutoIdVector &props) = 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 delete_(JSContext *cx, JSObject *proxy, jsid id, bool *bp) = 0;
|
||||||
virtual bool enumerate(JSContext *cx, JSObject *proxy, AutoIdVector &props) = 0;
|
virtual bool enumerate(JSContext *cx, JSObject *proxy,
|
||||||
virtual bool fix(JSContext *cx, JSObject *proxy, Value *vp) = 0;
|
AutoIdVector &props) = 0;
|
||||||
|
|
||||||
/* ES5 Harmony derived proxy traps. */
|
/* ES5 Harmony derived proxy traps. */
|
||||||
virtual bool has(JSContext *cx, JSObject *proxy, jsid id, bool *bp);
|
virtual bool has(JSContext *cx, JSObject *proxy, jsid id, bool *bp);
|
||||||
virtual bool hasOwn(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 get(JSContext *cx, JSObject *proxy, JSObject *receiver,
|
||||||
virtual bool set(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id, bool strict,
|
jsid id, Value *vp);
|
||||||
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 keys(JSContext *cx, JSObject *proxy, AutoIdVector &props);
|
||||||
virtual bool iterate(JSContext *cx, JSObject *proxy, unsigned flags, Value *vp);
|
virtual bool iterate(JSContext *cx, JSObject *proxy, unsigned flags,
|
||||||
|
Value *vp);
|
||||||
|
|
||||||
/* Spidermonkey extensions. */
|
/* Spidermonkey extensions. */
|
||||||
virtual bool call(JSContext *cx, JSObject *proxy, unsigned argc, Value *vp);
|
virtual bool call(JSContext *cx, JSObject *proxy, unsigned argc, Value *vp);
|
||||||
|
@ -88,17 +112,87 @@ class JS_FRIEND_API(ProxyHandler) {
|
||||||
virtual bool defaultValue(JSContext *cx, JSObject *obj, JSType hint, Value *vp);
|
virtual bool defaultValue(JSContext *cx, JSObject *obj, JSType hint, Value *vp);
|
||||||
virtual bool iteratorNext(JSContext *cx, JSObject *proxy, Value *vp);
|
virtual bool iteratorNext(JSContext *cx, JSObject *proxy, Value *vp);
|
||||||
virtual void finalize(JSFreeOp *fop, JSObject *proxy);
|
virtual void finalize(JSFreeOp *fop, JSObject *proxy);
|
||||||
virtual void trace(JSTracer *trc, JSObject *proxy);
|
|
||||||
virtual bool getElementIfPresent(JSContext *cx, JSObject *obj, JSObject *receiver,
|
virtual bool getElementIfPresent(JSContext *cx, JSObject *obj, JSObject *receiver,
|
||||||
uint32_t index, Value *vp, bool *present);
|
uint32_t index, Value *vp, bool *present);
|
||||||
|
};
|
||||||
|
|
||||||
virtual bool isOuterWindow() {
|
/*
|
||||||
return false;
|
* IndirectProxyHandler assumes that a target exists. Moreover, it assumes the
|
||||||
}
|
* target is a JSObject. Consequently, it provides default implementations for
|
||||||
|
* the fundamental traps that forward their behavior to the target. The derived
|
||||||
|
* traps, however, are inherited from BaseProxyHandler, and therefore still
|
||||||
|
* implemented in terms of the fundamental ones. This allows consumers of this
|
||||||
|
* class to define custom behavior without implementing the entire gamut of
|
||||||
|
* proxy traps.
|
||||||
|
*/
|
||||||
|
class JS_PUBLIC_API(IndirectProxyHandler) : public BaseProxyHandler {
|
||||||
|
public:
|
||||||
|
explicit IndirectProxyHandler(void *family);
|
||||||
|
|
||||||
inline void *family() {
|
/* ES5 Harmony fundamental proxy traps. */
|
||||||
return mFamily;
|
virtual bool getPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id,
|
||||||
}
|
bool set,
|
||||||
|
PropertyDescriptor *desc) MOZ_OVERRIDE;
|
||||||
|
virtual bool getOwnPropertyDescriptor(JSContext *cx, JSObject *proxy,
|
||||||
|
jsid id, bool set,
|
||||||
|
PropertyDescriptor *desc) MOZ_OVERRIDE;
|
||||||
|
virtual bool defineProperty(JSContext *cx, JSObject *proxy, jsid id,
|
||||||
|
PropertyDescriptor *desc) MOZ_OVERRIDE;
|
||||||
|
virtual bool getOwnPropertyNames(JSContext *cx, JSObject *proxy,
|
||||||
|
AutoIdVector &props) MOZ_OVERRIDE;
|
||||||
|
virtual bool delete_(JSContext *cx, JSObject *proxy, jsid id,
|
||||||
|
bool *bp) MOZ_OVERRIDE;
|
||||||
|
virtual bool enumerate(JSContext *cx, JSObject *proxy,
|
||||||
|
AutoIdVector &props) MOZ_OVERRIDE;
|
||||||
|
|
||||||
|
/* Spidermonkey extensions. */
|
||||||
|
virtual bool call(JSContext *cx, JSObject *proxy, unsigned argc,
|
||||||
|
Value *vp) MOZ_OVERRIDE;
|
||||||
|
virtual bool construct(JSContext *cx, JSObject *proxy, unsigned argc,
|
||||||
|
Value *argv, Value *rval) MOZ_OVERRIDE;
|
||||||
|
virtual bool nativeCall(JSContext *cx, JSObject *proxy, Class *clasp,
|
||||||
|
Native native, CallArgs args) MOZ_OVERRIDE;
|
||||||
|
virtual bool hasInstance(JSContext *cx, JSObject *proxy, 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 *proxy) MOZ_OVERRIDE;
|
||||||
|
virtual JSString *fun_toString(JSContext *cx, JSObject *proxy,
|
||||||
|
unsigned indent) MOZ_OVERRIDE;
|
||||||
|
virtual bool regexp_toShared(JSContext *cx, JSObject *proxy,
|
||||||
|
RegExpGuard *g) MOZ_OVERRIDE;
|
||||||
|
virtual bool defaultValue(JSContext *cx, JSObject *obj, JSType hint,
|
||||||
|
Value *vp) MOZ_OVERRIDE;
|
||||||
|
virtual bool iteratorNext(JSContext *cx, JSObject *proxy,
|
||||||
|
Value *vp) MOZ_OVERRIDE;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* DirectProxyHandler has the same assumptions about the target as its base,
|
||||||
|
* IndirectProxyHandler. Its fundamental traps are inherited from this class,
|
||||||
|
* and therefore forward their behavior to the target. The derived traps,
|
||||||
|
* however, are overrided so that, they too, forward their behavior to the
|
||||||
|
* target. This allows consumers of this class to forward to another object as
|
||||||
|
* transparently as possible.
|
||||||
|
*/
|
||||||
|
class JS_PUBLIC_API(DirectProxyHandler) : public IndirectProxyHandler {
|
||||||
|
public:
|
||||||
|
explicit DirectProxyHandler(void *family);
|
||||||
|
|
||||||
|
/* ES5 Harmony derived proxy traps. */
|
||||||
|
virtual bool has(JSContext *cx, JSObject *proxy, jsid id,
|
||||||
|
bool *bp) MOZ_OVERRIDE;
|
||||||
|
virtual bool hasOwn(JSContext *cx, JSObject *proxy, jsid id,
|
||||||
|
bool *bp) MOZ_OVERRIDE;
|
||||||
|
virtual bool get(JSContext *cx, JSObject *proxy, JSObject *receiver,
|
||||||
|
jsid id, Value *vp) MOZ_OVERRIDE;
|
||||||
|
virtual bool set(JSContext *cx, JSObject *proxy, JSObject *receiver,
|
||||||
|
jsid id, bool strict, Value *vp) MOZ_OVERRIDE;
|
||||||
|
virtual bool keys(JSContext *cx, JSObject *proxy,
|
||||||
|
AutoIdVector &props) MOZ_OVERRIDE;
|
||||||
|
virtual bool iterate(JSContext *cx, JSObject *proxy, unsigned flags,
|
||||||
|
Value *vp) MOZ_OVERRIDE;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Dispatch point for handlers that executes the appropriate C++ or scripted traps. */
|
/* Dispatch point for handlers that executes the appropriate C++ or scripted traps. */
|
||||||
|
@ -117,7 +211,6 @@ class Proxy {
|
||||||
static bool getOwnPropertyNames(JSContext *cx, JSObject *proxy, AutoIdVector &props);
|
static bool getOwnPropertyNames(JSContext *cx, JSObject *proxy, AutoIdVector &props);
|
||||||
static bool delete_(JSContext *cx, JSObject *proxy, jsid id, bool *bp);
|
static bool delete_(JSContext *cx, JSObject *proxy, jsid id, bool *bp);
|
||||||
static bool enumerate(JSContext *cx, JSObject *proxy, AutoIdVector &props);
|
static bool enumerate(JSContext *cx, JSObject *proxy, AutoIdVector &props);
|
||||||
static bool fix(JSContext *cx, JSObject *proxy, Value *vp);
|
|
||||||
|
|
||||||
/* ES5 Harmony derived proxy traps. */
|
/* ES5 Harmony derived proxy traps. */
|
||||||
static bool has(JSContext *cx, JSObject *proxy, jsid id, bool *bp);
|
static bool has(JSContext *cx, JSObject *proxy, jsid id, bool *bp);
|
||||||
|
@ -178,11 +271,11 @@ const uint32_t JSSLOT_PROXY_EXTRA = 2;
|
||||||
const uint32_t JSSLOT_PROXY_CALL = 4;
|
const uint32_t JSSLOT_PROXY_CALL = 4;
|
||||||
const uint32_t JSSLOT_PROXY_CONSTRUCT = 5;
|
const uint32_t JSSLOT_PROXY_CONSTRUCT = 5;
|
||||||
|
|
||||||
inline ProxyHandler *
|
inline BaseProxyHandler *
|
||||||
GetProxyHandler(const JSObject *obj)
|
GetProxyHandler(const JSObject *obj)
|
||||||
{
|
{
|
||||||
JS_ASSERT(IsProxy(obj));
|
JS_ASSERT(IsProxy(obj));
|
||||||
return (ProxyHandler *) GetReservedSlot(obj, JSSLOT_PROXY_HANDLER).toPrivate();
|
return (BaseProxyHandler *) GetReservedSlot(obj, JSSLOT_PROXY_HANDLER).toPrivate();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const Value &
|
inline const Value &
|
||||||
|
@ -192,6 +285,20 @@ GetProxyPrivate(const JSObject *obj)
|
||||||
return GetReservedSlot(obj, JSSLOT_PROXY_PRIVATE);
|
return GetReservedSlot(obj, JSSLOT_PROXY_PRIVATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline JSObject *
|
||||||
|
GetProxyTargetObject(const JSObject *obj)
|
||||||
|
{
|
||||||
|
JS_ASSERT(IsProxy(obj));
|
||||||
|
return GetProxyPrivate(obj).toObjectOrNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const Value &
|
||||||
|
GetProxyCall(const JSObject *obj)
|
||||||
|
{
|
||||||
|
JS_ASSERT(IsFunctionProxy(obj));
|
||||||
|
return GetReservedSlot(obj, JSSLOT_PROXY_CALL);
|
||||||
|
}
|
||||||
|
|
||||||
inline const Value &
|
inline const Value &
|
||||||
GetProxyExtra(const JSObject *obj, size_t n)
|
GetProxyExtra(const JSObject *obj, size_t n)
|
||||||
{
|
{
|
||||||
|
@ -200,16 +307,7 @@ GetProxyExtra(const JSObject *obj, size_t n)
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
SetProxyExtra(JSObject *obj, size_t n, const Value &extra)
|
SetProxyHandler(JSObject *obj, BaseProxyHandler *handler)
|
||||||
{
|
|
||||||
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));
|
JS_ASSERT(IsProxy(obj));
|
||||||
SetReservedSlot(obj, JSSLOT_PROXY_HANDLER, PrivateValue(handler));
|
SetReservedSlot(obj, JSSLOT_PROXY_HANDLER, PrivateValue(handler));
|
||||||
|
@ -222,8 +320,16 @@ SetProxyPrivate(JSObject *obj, const Value &value)
|
||||||
SetReservedSlot(obj, JSSLOT_PROXY_PRIVATE, value);
|
SetReservedSlot(obj, JSSLOT_PROXY_PRIVATE, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
JS_FRIEND_API(JSObject *)
|
JS_FRIEND_API(JSObject *)
|
||||||
NewProxyObject(JSContext *cx, ProxyHandler *handler, const Value &priv,
|
NewProxyObject(JSContext *cx, BaseProxyHandler *handler, const Value &priv,
|
||||||
JSObject *proto, JSObject *parent,
|
JSObject *proto, JSObject *parent,
|
||||||
JSObject *call = NULL, JSObject *construct = NULL);
|
JSObject *call = NULL, JSObject *construct = NULL);
|
||||||
|
|
||||||
|
|
|
@ -1,41 +1,8 @@
|
||||||
/* -*- 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 *****
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
* 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/. */
|
||||||
* 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___
|
#ifndef jsprvtd_h___
|
||||||
#define jsprvtd_h___
|
#define jsprvtd_h___
|
||||||
|
@ -84,7 +51,6 @@ typedef struct JSArgumentFormatMap JSArgumentFormatMap;
|
||||||
typedef struct JSGCThing JSGCThing;
|
typedef struct JSGCThing JSGCThing;
|
||||||
typedef struct JSGenerator JSGenerator;
|
typedef struct JSGenerator JSGenerator;
|
||||||
typedef struct JSNativeEnumerator JSNativeEnumerator;
|
typedef struct JSNativeEnumerator JSNativeEnumerator;
|
||||||
typedef struct JSProperty JSProperty;
|
|
||||||
typedef struct JSSharpObjectMap JSSharpObjectMap;
|
typedef struct JSSharpObjectMap JSSharpObjectMap;
|
||||||
typedef struct JSTryNote JSTryNote;
|
typedef struct JSTryNote JSTryNote;
|
||||||
|
|
||||||
|
@ -95,7 +61,10 @@ typedef struct JSPrinter JSPrinter;
|
||||||
typedef struct JSStackHeader JSStackHeader;
|
typedef struct JSStackHeader JSStackHeader;
|
||||||
typedef struct JSSubString JSSubString;
|
typedef struct JSSubString JSSubString;
|
||||||
typedef struct JSSpecializedNative JSSpecializedNative;
|
typedef struct JSSpecializedNative JSSpecializedNative;
|
||||||
|
|
||||||
|
#if JS_HAS_XML_SUPPORT
|
||||||
typedef struct JSXML JSXML;
|
typedef struct JSXML JSXML;
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Template declarations.
|
* Template declarations.
|
||||||
|
@ -160,9 +129,7 @@ class StackFrame;
|
||||||
class StackSegment;
|
class StackSegment;
|
||||||
class StackSpace;
|
class StackSpace;
|
||||||
class ContextStack;
|
class ContextStack;
|
||||||
class FrameRegsIter;
|
class ScriptFrameIter;
|
||||||
class CallReceiver;
|
|
||||||
class CallArgs;
|
|
||||||
|
|
||||||
struct BytecodeEmitter;
|
struct BytecodeEmitter;
|
||||||
struct Definition;
|
struct Definition;
|
||||||
|
@ -170,6 +137,7 @@ struct FunctionBox;
|
||||||
struct ObjectBox;
|
struct ObjectBox;
|
||||||
struct ParseNode;
|
struct ParseNode;
|
||||||
struct Parser;
|
struct Parser;
|
||||||
|
struct SharedContext;
|
||||||
class TokenStream;
|
class TokenStream;
|
||||||
struct Token;
|
struct Token;
|
||||||
struct TokenPos;
|
struct TokenPos;
|
||||||
|
@ -178,8 +146,8 @@ struct TreeContext;
|
||||||
class UpvarCookie;
|
class UpvarCookie;
|
||||||
|
|
||||||
class Proxy;
|
class Proxy;
|
||||||
class ProxyHandler;
|
class BaseProxyHandler;
|
||||||
class Wrapper;
|
class DirectWrapper;
|
||||||
class CrossCompartmentWrapper;
|
class CrossCompartmentWrapper;
|
||||||
|
|
||||||
class TempAllocPolicy;
|
class TempAllocPolicy;
|
||||||
|
@ -206,10 +174,9 @@ struct StackShape;
|
||||||
|
|
||||||
class MultiDeclRange;
|
class MultiDeclRange;
|
||||||
class ParseMapPool;
|
class ParseMapPool;
|
||||||
class DefnOrHeader;
|
class DefinitionList;
|
||||||
typedef InlineMap<JSAtom *, Definition *, 24> AtomDefnMap;
|
typedef InlineMap<JSAtom *, Definition *, 24> AtomDefnMap;
|
||||||
typedef InlineMap<JSAtom *, jsatomid, 24> AtomIndexMap;
|
typedef InlineMap<JSAtom *, jsatomid, 24> AtomIndexMap;
|
||||||
typedef InlineMap<JSAtom *, DefnOrHeader, 24> AtomDOHMap;
|
|
||||||
typedef Vector<UpvarCookie, 8> UpvarCookies;
|
typedef Vector<UpvarCookie, 8> UpvarCookies;
|
||||||
|
|
||||||
class Breakpoint;
|
class Breakpoint;
|
||||||
|
@ -256,17 +223,13 @@ typedef JS::Handle<types::TypeObject*> HandleTypeObject;
|
||||||
typedef JS::Handle<JSAtom*> HandleAtom;
|
typedef JS::Handle<JSAtom*> HandleAtom;
|
||||||
typedef JS::Handle<PropertyName*> HandlePropertyName;
|
typedef JS::Handle<PropertyName*> HandlePropertyName;
|
||||||
|
|
||||||
typedef JS::Root<Shape*> RootShape;
|
typedef JS::MutableHandle<Shape*> MutableHandleShape;
|
||||||
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::Rooted<Shape*> RootedShape;
|
||||||
typedef JS::RootedVar<BaseShape*> RootedVarBaseShape;
|
typedef JS::Rooted<BaseShape*> RootedBaseShape;
|
||||||
typedef JS::RootedVar<types::TypeObject*> RootedVarTypeObject;
|
typedef JS::Rooted<types::TypeObject*> RootedTypeObject;
|
||||||
typedef JS::RootedVar<JSAtom*> RootedVarAtom;
|
typedef JS::Rooted<JSAtom*> RootedAtom;
|
||||||
typedef JS::RootedVar<PropertyName*> RootedVarPropertyName;
|
typedef JS::Rooted<PropertyName*> RootedPropertyName;
|
||||||
|
|
||||||
enum XDRMode {
|
enum XDRMode {
|
||||||
XDR_ENCODE,
|
XDR_ENCODE,
|
||||||
|
@ -404,41 +367,23 @@ typedef struct JSDebugHooks {
|
||||||
|
|
||||||
/* js::ObjectOps function pointer typedefs. */
|
/* 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
|
* A generic type for functions mapping an object to another object, or null
|
||||||
* if an error or exception was thrown on cx.
|
* if an error or exception was thrown on cx.
|
||||||
*/
|
*/
|
||||||
typedef JSObject *
|
typedef JSObject *
|
||||||
(* JSObjectOp)(JSContext *cx, JSObject *obj);
|
(* JSObjectOp)(JSContext *cx, JSHandleObject obj);
|
||||||
|
|
||||||
|
/* Signature for class initialization ops. */
|
||||||
|
typedef JSObject *
|
||||||
|
(* JSClassInitializerOp)(JSContext *cx, JSObject *obj);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Hook that creates an iterator object for a given object. Returns the
|
* 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.
|
* iterator object or null if an error or exception was thrown on cx.
|
||||||
*/
|
*/
|
||||||
typedef JSObject *
|
typedef JSObject *
|
||||||
(* JSIteratorOp)(JSContext *cx, JSObject *obj, JSBool keysonly);
|
(* JSIteratorOp)(JSContext *cx, JSHandleObject obj, JSBool keysonly);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The following determines whether JS_EncodeCharacters and JS_DecodeBytes
|
* The following determines whether JS_EncodeCharacters and JS_DecodeBytes
|
||||||
|
|
|
@ -1,41 +1,8 @@
|
||||||
/* -*- 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 *****
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
* 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/. */
|
||||||
* 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 jspubtd_h___
|
#ifndef jspubtd_h___
|
||||||
#define jspubtd_h___
|
#define jspubtd_h___
|
||||||
|
@ -148,7 +115,11 @@ typedef enum JSProtoKey {
|
||||||
/* js_CheckAccess mode enumeration. */
|
/* js_CheckAccess mode enumeration. */
|
||||||
typedef enum JSAccessMode {
|
typedef enum JSAccessMode {
|
||||||
JSACC_PROTO = 0, /* XXXbe redundant w.r.t. id */
|
JSACC_PROTO = 0, /* XXXbe redundant w.r.t. id */
|
||||||
JSACC_PARENT = 1, /* XXXbe redundant w.r.t. id */
|
|
||||||
|
/*
|
||||||
|
* enum value #1 formerly called JSACC_PARENT,
|
||||||
|
* gap preserved for ABI compatibility.
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* enum value #2 formerly called JSACC_IMPORT,
|
* enum value #2 formerly called JSACC_IMPORT,
|
||||||
|
@ -249,7 +220,7 @@ JS_END_EXTERN_C
|
||||||
namespace JS {
|
namespace JS {
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class Root;
|
class Rooted;
|
||||||
|
|
||||||
class SkipRoot;
|
class SkipRoot;
|
||||||
|
|
||||||
|
@ -261,8 +232,11 @@ enum ThingRootKind
|
||||||
THING_ROOT_TYPE_OBJECT,
|
THING_ROOT_TYPE_OBJECT,
|
||||||
THING_ROOT_STRING,
|
THING_ROOT_STRING,
|
||||||
THING_ROOT_SCRIPT,
|
THING_ROOT_SCRIPT,
|
||||||
|
THING_ROOT_XML,
|
||||||
THING_ROOT_ID,
|
THING_ROOT_ID,
|
||||||
|
THING_ROOT_PROPERTY_ID,
|
||||||
THING_ROOT_VALUE,
|
THING_ROOT_VALUE,
|
||||||
|
THING_ROOT_TYPE,
|
||||||
THING_ROOT_LIMIT
|
THING_ROOT_LIMIT
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -280,15 +254,15 @@ struct ContextFriendFields {
|
||||||
return reinterpret_cast<ContextFriendFields *>(cx);
|
return reinterpret_cast<ContextFriendFields *>(cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef JSGC_ROOT_ANALYSIS
|
#if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Stack allocated GC roots for stack GC heap pointers, which may be
|
* Stack allocated GC roots for stack GC heap pointers, which may be
|
||||||
* overwritten if moved during a GC.
|
* overwritten if moved during a GC.
|
||||||
*/
|
*/
|
||||||
Root<void*> *thingGCRooters[THING_ROOT_LIMIT];
|
Rooted<void*> *thingGCRooters[THING_ROOT_LIMIT];
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef DEBUG
|
#if defined(DEBUG) && defined(JS_GC_ZEAL) && defined(JSGC_ROOT_ANALYSIS) && !defined(JS_THREADSAFE)
|
||||||
/*
|
/*
|
||||||
* Stack allocated list of stack locations which hold non-relocatable
|
* Stack allocated list of stack locations which hold non-relocatable
|
||||||
* GC heap pointers (where the target is rooted somewhere else) or integer
|
* GC heap pointers (where the target is rooted somewhere else) or integer
|
||||||
|
@ -299,8 +273,6 @@ struct ContextFriendFields {
|
||||||
*/
|
*/
|
||||||
SkipRoot *skipGCRooters;
|
SkipRoot *skipGCRooters;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* JSGC_ROOT_ANALYSIS */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} /* namespace JS */
|
} /* namespace JS */
|
||||||
|
|
|
@ -1,364 +0,0 @@
|
||||||
/* -*- Mode: c++; c-basic-offset: 4; tab-width: 40; indent-tabs-mode: nil -*- */
|
|
||||||
/* vim: set ts=40 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 WebGL impl
|
|
||||||
*
|
|
||||||
* 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):
|
|
||||||
* Vladimir Vukicevic <vladimir@pobox.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 jstypedarray_h
|
|
||||||
#define jstypedarray_h
|
|
||||||
|
|
||||||
#include "jsapi.h"
|
|
||||||
#include "jsclass.h"
|
|
||||||
|
|
||||||
#include "gc/Barrier.h"
|
|
||||||
|
|
||||||
typedef struct JSProperty JSProperty;
|
|
||||||
|
|
||||||
namespace js {
|
|
||||||
|
|
||||||
/*
|
|
||||||
* ArrayBuffer
|
|
||||||
*
|
|
||||||
* This class holds the underlying raw buffer that the TypedArray
|
|
||||||
* subclasses access. It can be created explicitly and passed to a
|
|
||||||
* TypedArray subclass, or can be created implicitly by constructing a
|
|
||||||
* TypedArray with a size.
|
|
||||||
*/
|
|
||||||
struct JS_FRIEND_API(ArrayBuffer) {
|
|
||||||
static Class slowClass;
|
|
||||||
static JSPropertySpec jsprops[];
|
|
||||||
static JSFunctionSpec jsfuncs[];
|
|
||||||
|
|
||||||
static JSBool prop_getByteLength(JSContext *cx, JSObject *obj, jsid id, Value *vp);
|
|
||||||
|
|
||||||
static JSBool fun_slice(JSContext *cx, unsigned argc, Value *vp);
|
|
||||||
|
|
||||||
static JSBool class_constructor(JSContext *cx, unsigned argc, Value *vp);
|
|
||||||
|
|
||||||
static JSObject *create(JSContext *cx, int32_t nbytes, uint8_t *contents = NULL);
|
|
||||||
|
|
||||||
static JSObject *createSlice(JSContext *cx, JSObject *arrayBuffer,
|
|
||||||
uint32_t begin, uint32_t end);
|
|
||||||
|
|
||||||
ArrayBuffer()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
~ArrayBuffer();
|
|
||||||
|
|
||||||
static void
|
|
||||||
obj_trace(JSTracer *trc, JSObject *obj);
|
|
||||||
|
|
||||||
static JSBool
|
|
||||||
obj_lookupGeneric(JSContext *cx, JSObject *obj, jsid id,
|
|
||||||
JSObject **objp, JSProperty **propp);
|
|
||||||
static JSBool
|
|
||||||
obj_lookupProperty(JSContext *cx, JSObject *obj, PropertyName *name,
|
|
||||||
JSObject **objp, JSProperty **propp);
|
|
||||||
static JSBool
|
|
||||||
obj_lookupElement(JSContext *cx, JSObject *obj, uint32_t index,
|
|
||||||
JSObject **objp, JSProperty **propp);
|
|
||||||
static JSBool
|
|
||||||
obj_lookupSpecial(JSContext *cx, JSObject *obj, SpecialId sid, JSObject **objp,
|
|
||||||
JSProperty **propp);
|
|
||||||
|
|
||||||
static JSBool
|
|
||||||
obj_defineGeneric(JSContext *cx, JSObject *obj, jsid id, const Value *v,
|
|
||||||
PropertyOp getter, StrictPropertyOp setter, unsigned attrs);
|
|
||||||
static JSBool
|
|
||||||
obj_defineProperty(JSContext *cx, JSObject *obj, PropertyName *name, const Value *v,
|
|
||||||
PropertyOp getter, StrictPropertyOp setter, unsigned attrs);
|
|
||||||
static JSBool
|
|
||||||
obj_defineElement(JSContext *cx, JSObject *obj, uint32_t index, const Value *v,
|
|
||||||
PropertyOp getter, StrictPropertyOp setter, unsigned attrs);
|
|
||||||
static JSBool
|
|
||||||
obj_defineSpecial(JSContext *cx, JSObject *obj, SpecialId sid, const Value *v,
|
|
||||||
PropertyOp getter, StrictPropertyOp setter, unsigned attrs);
|
|
||||||
|
|
||||||
static JSBool
|
|
||||||
obj_getGeneric(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp);
|
|
||||||
|
|
||||||
static JSBool
|
|
||||||
obj_getProperty(JSContext *cx, JSObject *obj, JSObject *receiver, PropertyName *name,
|
|
||||||
Value *vp);
|
|
||||||
|
|
||||||
static JSBool
|
|
||||||
obj_getElement(JSContext *cx, JSObject *obj, JSObject *receiver, uint32_t index, Value *vp);
|
|
||||||
static JSBool
|
|
||||||
obj_getElementIfPresent(JSContext *cx, JSObject *obj, JSObject *receiver, uint32_t index,
|
|
||||||
Value *vp, bool *present);
|
|
||||||
|
|
||||||
static JSBool
|
|
||||||
obj_getSpecial(JSContext *cx, JSObject *obj, JSObject *receiver, SpecialId sid, Value *vp);
|
|
||||||
|
|
||||||
static JSBool
|
|
||||||
obj_setGeneric(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict);
|
|
||||||
static JSBool
|
|
||||||
obj_setProperty(JSContext *cx, JSObject *obj, PropertyName *name, Value *vp, JSBool strict);
|
|
||||||
static JSBool
|
|
||||||
obj_setElement(JSContext *cx, JSObject *obj, uint32_t index, Value *vp, JSBool strict);
|
|
||||||
static JSBool
|
|
||||||
obj_setSpecial(JSContext *cx, JSObject *obj, SpecialId sid, Value *vp, JSBool strict);
|
|
||||||
|
|
||||||
static JSBool
|
|
||||||
obj_getGenericAttributes(JSContext *cx, JSObject *obj, jsid id, unsigned *attrsp);
|
|
||||||
static JSBool
|
|
||||||
obj_getPropertyAttributes(JSContext *cx, JSObject *obj, PropertyName *name, unsigned *attrsp);
|
|
||||||
static JSBool
|
|
||||||
obj_getElementAttributes(JSContext *cx, JSObject *obj, uint32_t index, unsigned *attrsp);
|
|
||||||
static JSBool
|
|
||||||
obj_getSpecialAttributes(JSContext *cx, JSObject *obj, SpecialId sid, unsigned *attrsp);
|
|
||||||
|
|
||||||
static JSBool
|
|
||||||
obj_setGenericAttributes(JSContext *cx, JSObject *obj, jsid id, unsigned *attrsp);
|
|
||||||
static JSBool
|
|
||||||
obj_setPropertyAttributes(JSContext *cx, JSObject *obj, PropertyName *name, unsigned *attrsp);
|
|
||||||
static JSBool
|
|
||||||
obj_setElementAttributes(JSContext *cx, JSObject *obj, uint32_t index, unsigned *attrsp);
|
|
||||||
static JSBool
|
|
||||||
obj_setSpecialAttributes(JSContext *cx, JSObject *obj, SpecialId sid, unsigned *attrsp);
|
|
||||||
|
|
||||||
static JSBool
|
|
||||||
obj_deleteProperty(JSContext *cx, JSObject *obj, PropertyName *name, Value *rval, JSBool strict);
|
|
||||||
static JSBool
|
|
||||||
obj_deleteElement(JSContext *cx, JSObject *obj, uint32_t index, Value *rval, JSBool strict);
|
|
||||||
static JSBool
|
|
||||||
obj_deleteSpecial(JSContext *cx, JSObject *obj, SpecialId sid, Value *rval, JSBool strict);
|
|
||||||
|
|
||||||
static JSBool
|
|
||||||
obj_enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
|
|
||||||
Value *statep, jsid *idp);
|
|
||||||
|
|
||||||
static JSType
|
|
||||||
obj_typeOf(JSContext *cx, JSObject *obj);
|
|
||||||
|
|
||||||
static JSObject *
|
|
||||||
getArrayBuffer(JSObject *obj);
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* TypedArray
|
|
||||||
*
|
|
||||||
* The non-templated base class for the specific typed implementations.
|
|
||||||
* This class holds all the member variables that are used by
|
|
||||||
* the subclasses.
|
|
||||||
*/
|
|
||||||
|
|
||||||
struct JS_FRIEND_API(TypedArray) {
|
|
||||||
enum {
|
|
||||||
TYPE_INT8 = 0,
|
|
||||||
TYPE_UINT8,
|
|
||||||
TYPE_INT16,
|
|
||||||
TYPE_UINT16,
|
|
||||||
TYPE_INT32,
|
|
||||||
TYPE_UINT32,
|
|
||||||
TYPE_FLOAT32,
|
|
||||||
TYPE_FLOAT64,
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Special type that's a uint8, but assignments are clamped to 0 .. 255.
|
|
||||||
* Treat the raw data type as a uint8.
|
|
||||||
*/
|
|
||||||
TYPE_UINT8_CLAMPED,
|
|
||||||
|
|
||||||
TYPE_MAX
|
|
||||||
};
|
|
||||||
|
|
||||||
enum {
|
|
||||||
/* Properties of the typed array stored in reserved slots. */
|
|
||||||
FIELD_LENGTH = 0,
|
|
||||||
FIELD_BYTEOFFSET,
|
|
||||||
FIELD_BYTELENGTH,
|
|
||||||
FIELD_TYPE,
|
|
||||||
FIELD_BUFFER,
|
|
||||||
FIELD_MAX,
|
|
||||||
NUM_FIXED_SLOTS = 7
|
|
||||||
};
|
|
||||||
|
|
||||||
// and MUST NOT be used to construct new objects.
|
|
||||||
static Class fastClasses[TYPE_MAX];
|
|
||||||
|
|
||||||
// These are the slow/original classes, used
|
|
||||||
// fo constructing new objects
|
|
||||||
static Class slowClasses[TYPE_MAX];
|
|
||||||
|
|
||||||
static JSPropertySpec jsprops[];
|
|
||||||
|
|
||||||
static JSObject *getTypedArray(JSObject *obj);
|
|
||||||
|
|
||||||
static JSBool prop_getBuffer(JSContext *cx, JSObject *obj, jsid id, Value *vp);
|
|
||||||
static JSBool prop_getByteOffset(JSContext *cx, JSObject *obj, jsid id, Value *vp);
|
|
||||||
static JSBool prop_getByteLength(JSContext *cx, JSObject *obj, jsid id, Value *vp);
|
|
||||||
static JSBool prop_getLength(JSContext *cx, JSObject *obj, jsid id, Value *vp);
|
|
||||||
|
|
||||||
static JSBool obj_lookupGeneric(JSContext *cx, JSObject *obj, jsid id,
|
|
||||||
JSObject **objp, JSProperty **propp);
|
|
||||||
static JSBool obj_lookupProperty(JSContext *cx, JSObject *obj, PropertyName *name,
|
|
||||||
JSObject **objp, JSProperty **propp);
|
|
||||||
static JSBool obj_lookupElement(JSContext *cx, JSObject *obj, uint32_t index,
|
|
||||||
JSObject **objp, JSProperty **propp);
|
|
||||||
static JSBool obj_lookupSpecial(JSContext *cx, JSObject *obj, SpecialId sid,
|
|
||||||
JSObject **objp, JSProperty **propp);
|
|
||||||
|
|
||||||
static JSBool obj_getGenericAttributes(JSContext *cx, JSObject *obj, jsid id, unsigned *attrsp);
|
|
||||||
static JSBool obj_getPropertyAttributes(JSContext *cx, JSObject *obj, PropertyName *name, unsigned *attrsp);
|
|
||||||
static JSBool obj_getElementAttributes(JSContext *cx, JSObject *obj, uint32_t index, unsigned *attrsp);
|
|
||||||
static JSBool obj_getSpecialAttributes(JSContext *cx, JSObject *obj, SpecialId sid, unsigned *attrsp);
|
|
||||||
|
|
||||||
static JSBool obj_setGenericAttributes(JSContext *cx, JSObject *obj, jsid id, unsigned *attrsp);
|
|
||||||
static JSBool obj_setPropertyAttributes(JSContext *cx, JSObject *obj, PropertyName *name, unsigned *attrsp);
|
|
||||||
static JSBool obj_setElementAttributes(JSContext *cx, JSObject *obj, uint32_t index, unsigned *attrsp);
|
|
||||||
static JSBool obj_setSpecialAttributes(JSContext *cx, JSObject *obj, SpecialId sid, unsigned *attrsp);
|
|
||||||
|
|
||||||
static uint32_t getLength(JSObject *obj);
|
|
||||||
static uint32_t getByteOffset(JSObject *obj);
|
|
||||||
static uint32_t getByteLength(JSObject *obj);
|
|
||||||
static uint32_t getType(JSObject *obj);
|
|
||||||
static JSObject * getBuffer(JSObject *obj);
|
|
||||||
static void * getDataOffset(JSObject *obj);
|
|
||||||
|
|
||||||
public:
|
|
||||||
static bool
|
|
||||||
isArrayIndex(JSContext *cx, JSObject *obj, jsid id, uint32_t *ip = NULL);
|
|
||||||
|
|
||||||
static inline uint32_t slotWidth(int atype) {
|
|
||||||
switch (atype) {
|
|
||||||
case js::TypedArray::TYPE_INT8:
|
|
||||||
case js::TypedArray::TYPE_UINT8:
|
|
||||||
case js::TypedArray::TYPE_UINT8_CLAMPED:
|
|
||||||
return 1;
|
|
||||||
case js::TypedArray::TYPE_INT16:
|
|
||||||
case js::TypedArray::TYPE_UINT16:
|
|
||||||
return 2;
|
|
||||||
case js::TypedArray::TYPE_INT32:
|
|
||||||
case js::TypedArray::TYPE_UINT32:
|
|
||||||
case js::TypedArray::TYPE_FLOAT32:
|
|
||||||
return 4;
|
|
||||||
case js::TypedArray::TYPE_FLOAT64:
|
|
||||||
return 8;
|
|
||||||
default:
|
|
||||||
JS_NOT_REACHED("invalid typed array type");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int slotWidth(JSObject *obj) {
|
|
||||||
return slotWidth(getType(obj));
|
|
||||||
}
|
|
||||||
|
|
||||||
static int lengthOffset();
|
|
||||||
static int dataOffset();
|
|
||||||
};
|
|
||||||
|
|
||||||
extern bool
|
|
||||||
IsFastTypedArrayClass(const Class *clasp);
|
|
||||||
|
|
||||||
} // namespace js
|
|
||||||
|
|
||||||
/* Friend API methods */
|
|
||||||
|
|
||||||
JS_FRIEND_API(JSObject *)
|
|
||||||
js_InitTypedArrayClasses(JSContext *cx, JSObject *obj);
|
|
||||||
|
|
||||||
JS_FRIEND_API(JSBool)
|
|
||||||
js_IsTypedArray(JSObject *obj);
|
|
||||||
|
|
||||||
JS_FRIEND_API(JSBool)
|
|
||||||
js_IsArrayBuffer(JSObject *obj);
|
|
||||||
|
|
||||||
JS_FRIEND_API(JSObject *)
|
|
||||||
js_CreateArrayBuffer(JSContext *cx, uint32_t nbytes);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Create a new typed array of type atype (one of the TypedArray
|
|
||||||
* enumerant values above), with nelements elements.
|
|
||||||
*/
|
|
||||||
JS_FRIEND_API(JSObject *)
|
|
||||||
js_CreateTypedArray(JSContext *cx, int atype, uint32_t nelements);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Create a new typed array of type atype (one of the TypedArray
|
|
||||||
* enumerant values above), and copy in values from the given JSObject,
|
|
||||||
* which must either be a typed array or an array-like object.
|
|
||||||
*/
|
|
||||||
JS_FRIEND_API(JSObject *)
|
|
||||||
js_CreateTypedArrayWithArray(JSContext *cx, int atype, JSObject *arrayArg);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Create a new typed array of type atype (one of the TypedArray
|
|
||||||
* enumerant values above), using a given ArrayBuffer for storage.
|
|
||||||
* The byteoffset and length values are optional; if -1 is passed, an
|
|
||||||
* offset of 0 and enough elements to use up the remainder of the byte
|
|
||||||
* array are used as the default values.
|
|
||||||
*/
|
|
||||||
JS_FRIEND_API(JSObject *)
|
|
||||||
js_CreateTypedArrayWithBuffer(JSContext *cx, int atype, JSObject *bufArg,
|
|
||||||
int byteoffset, int length);
|
|
||||||
|
|
||||||
extern int32_t JS_FASTCALL
|
|
||||||
js_TypedArray_uint8_clamp_double(const double x);
|
|
||||||
|
|
||||||
JS_FRIEND_API(JSBool)
|
|
||||||
JS_IsArrayBufferObject(JSObject *obj);
|
|
||||||
|
|
||||||
JS_FRIEND_API(JSObject *)
|
|
||||||
JS_NewArrayBuffer(JSContext *cx, uint32_t nbytes);
|
|
||||||
|
|
||||||
JS_FRIEND_API(uint32_t)
|
|
||||||
JS_GetArrayBufferByteLength(JSObject *obj);
|
|
||||||
|
|
||||||
JS_FRIEND_API(uint8_t *)
|
|
||||||
JS_GetArrayBufferData(JSObject *obj);
|
|
||||||
|
|
||||||
JS_FRIEND_API(uint32_t)
|
|
||||||
JS_GetTypedArrayLength(JSObject *obj);
|
|
||||||
|
|
||||||
JS_FRIEND_API(uint32_t)
|
|
||||||
JS_GetTypedArrayByteOffset(JSObject *obj);
|
|
||||||
|
|
||||||
JS_FRIEND_API(uint32_t)
|
|
||||||
JS_GetTypedArrayByteLength(JSObject *obj);
|
|
||||||
|
|
||||||
JS_FRIEND_API(uint32_t)
|
|
||||||
JS_GetTypedArrayType(JSObject *obj);
|
|
||||||
|
|
||||||
JS_FRIEND_API(JSObject *)
|
|
||||||
JS_GetTypedArrayBuffer(JSObject *obj);
|
|
||||||
|
|
||||||
JS_FRIEND_API(void *)
|
|
||||||
JS_GetTypedArrayData(JSObject *obj);
|
|
||||||
|
|
||||||
#endif /* jstypedarray_h */
|
|
|
@ -1,41 +1,7 @@
|
||||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
/* ***** BEGIN LICENSE BLOCK *****
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
* 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/. */
|
||||||
* 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):
|
|
||||||
* IBM Corp.
|
|
||||||
*
|
|
||||||
* 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: jstypes.h
|
** File: jstypes.h
|
||||||
|
|
|
@ -1,41 +1,8 @@
|
||||||
/* -*- 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 *****
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
* 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/. */
|
||||||
* 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 ***** */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* PR assertion checker.
|
* PR assertion checker.
|
||||||
|
@ -410,14 +377,8 @@ inline __attribute__ ((unused)) void MUST_FLOW_THROUGH(const char *label) {}
|
||||||
#endif
|
#endif
|
||||||
#ifdef JS_CRASH_DIAGNOSTICS
|
#ifdef JS_CRASH_DIAGNOSTICS
|
||||||
# define JS_POISON(p, val, size) memset((p), (val), (size))
|
# 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
|
#else
|
||||||
# define JS_POISON(p, val, size) ((void) 0)
|
# 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
|
#endif
|
||||||
|
|
||||||
/* Basic stats */
|
/* Basic stats */
|
||||||
|
|
|
@ -1,41 +1,9 @@
|
||||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||||
* vim: set ts=4 sw=4 et tw=99 ft=cpp:
|
* vim: set ts=4 sw=4 et tw=99 ft=cpp:
|
||||||
*
|
*
|
||||||
* ***** BEGIN LICENSE BLOCK *****
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
* 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/. */
|
||||||
* 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
|
|
||||||
* June 30, 2010
|
|
||||||
*
|
|
||||||
* The Initial Developer of the Original Code is
|
|
||||||
* the Mozilla Corporation.
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* Luke Wagner <lw@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 jsvalimpl_h__
|
#ifndef jsvalimpl_h__
|
||||||
#define jsvalimpl_h__
|
#define jsvalimpl_h__
|
||||||
|
@ -44,8 +12,6 @@
|
||||||
* Implementation details for js::Value in jsapi.h.
|
* Implementation details for js::Value in jsapi.h.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "mozilla/FloatingPoint.h"
|
|
||||||
|
|
||||||
#include "js/Utility.h"
|
#include "js/Utility.h"
|
||||||
|
|
||||||
JS_BEGIN_EXTERN_C
|
JS_BEGIN_EXTERN_C
|
||||||
|
@ -247,10 +213,11 @@ typedef enum JSWhyMagic
|
||||||
JS_ARG_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_SERIALIZE_NO_NODE, /* an empty subnode in the AST serializer */
|
||||||
JS_LAZY_ARGUMENTS, /* lazy arguments value on the stack */
|
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_OPTIMIZED_ARGUMENTS, /* optimized-away 'arguments' value */
|
||||||
JS_IS_CONSTRUCTING, /* magic value passed to natives to indicate construction */
|
JS_IS_CONSTRUCTING, /* magic value passed to natives to indicate construction */
|
||||||
JS_OVERWRITTEN_CALLEE, /* arguments.callee has been overwritten */
|
JS_OVERWRITTEN_CALLEE, /* arguments.callee has been overwritten */
|
||||||
|
JS_FORWARD_TO_CALL_OBJECT, /* args object element stored in call object */
|
||||||
|
JS_BLOCK_NEEDS_CLONE, /* value of static block object slot */
|
||||||
JS_GENERIC_MAGIC /* for local use */
|
JS_GENERIC_MAGIC /* for local use */
|
||||||
} JSWhyMagic;
|
} JSWhyMagic;
|
||||||
|
|
||||||
|
@ -269,6 +236,7 @@ typedef union jsval_layout
|
||||||
void *ptr;
|
void *ptr;
|
||||||
JSWhyMagic why;
|
JSWhyMagic why;
|
||||||
size_t word;
|
size_t word;
|
||||||
|
uintptr_t uintptr;
|
||||||
} payload;
|
} payload;
|
||||||
JSValueTag tag;
|
JSValueTag tag;
|
||||||
} s;
|
} s;
|
||||||
|
@ -296,6 +264,7 @@ typedef union jsval_layout
|
||||||
double asDouble;
|
double asDouble;
|
||||||
void *asPtr;
|
void *asPtr;
|
||||||
size_t asWord;
|
size_t asWord;
|
||||||
|
uintptr_t asUIntPtr;
|
||||||
} JSVAL_ALIGNMENT jsval_layout;
|
} JSVAL_ALIGNMENT jsval_layout;
|
||||||
# endif /* JS_BITS_PER_WORD */
|
# endif /* JS_BITS_PER_WORD */
|
||||||
#else /* defined(IS_LITTLE_ENDIAN) */
|
#else /* defined(IS_LITTLE_ENDIAN) */
|
||||||
|
@ -314,6 +283,7 @@ typedef union jsval_layout
|
||||||
void *ptr;
|
void *ptr;
|
||||||
JSWhyMagic why;
|
JSWhyMagic why;
|
||||||
size_t word;
|
size_t word;
|
||||||
|
uintptr_t uintptr;
|
||||||
} payload;
|
} payload;
|
||||||
} s;
|
} s;
|
||||||
double asDouble;
|
double asDouble;
|
||||||
|
@ -338,6 +308,7 @@ typedef union jsval_layout
|
||||||
double asDouble;
|
double asDouble;
|
||||||
void *asPtr;
|
void *asPtr;
|
||||||
size_t asWord;
|
size_t asWord;
|
||||||
|
uintptr_t asUIntPtr;
|
||||||
} JSVAL_ALIGNMENT jsval_layout;
|
} JSVAL_ALIGNMENT jsval_layout;
|
||||||
# endif /* JS_BITS_PER_WORD */
|
# endif /* JS_BITS_PER_WORD */
|
||||||
#endif /* defined(IS_LITTLE_ENDIAN) */
|
#endif /* defined(IS_LITTLE_ENDIAN) */
|
||||||
|
|
|
@ -1,41 +1,8 @@
|
||||||
/* -*- 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 *****
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
* 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/. */
|
||||||
* 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 ***** */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* JS configuration macros.
|
* JS configuration macros.
|
||||||
|
@ -91,7 +58,6 @@
|
||||||
#define JS_HAS_CONST 0 /* has JS2 const as alternative var */
|
#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_FUN_EXPR_STMT 0 /* has function expression statement */
|
||||||
#define JS_HAS_NO_SUCH_METHOD 0 /* has o.__noSuchMethod__ handler */
|
#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_GENERATORS 0 /* has yield in generator function */
|
#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_BLOCK_SCOPE 0 /* has block scope via let/arraycomp */
|
||||||
#define JS_HAS_DESTRUCTURING 0 /* has [a,b] = ... or {p:a,q:b} = ... */
|
#define JS_HAS_DESTRUCTURING 0 /* has [a,b] = ... or {p:a,q:b} = ... */
|
||||||
|
@ -113,7 +79,6 @@
|
||||||
#define JS_HAS_CONST 1 /* has JS2 const as alternative var */
|
#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_FUN_EXPR_STMT 1 /* has function expression statement */
|
||||||
#define JS_HAS_NO_SUCH_METHOD 1 /* has o.__noSuchMethod__ handler */
|
#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_GENERATORS 0 /* has yield in generator function */
|
#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_BLOCK_SCOPE 0 /* has block scope via let/arraycomp */
|
||||||
#define JS_HAS_DESTRUCTURING 0 /* has [a,b] = ... or {p:a,q:b} = ... */
|
#define JS_HAS_DESTRUCTURING 0 /* has [a,b] = ... or {p:a,q:b} = ... */
|
||||||
|
@ -131,7 +96,6 @@
|
||||||
#define JS_HAS_CONST 1 /* has JS2 const as alternative var */
|
#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_FUN_EXPR_STMT 1 /* has function expression statement */
|
||||||
#define JS_HAS_NO_SUCH_METHOD 1 /* has o.__noSuchMethod__ handler */
|
#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_GENERATORS 0 /* has yield in generator function */
|
#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_BLOCK_SCOPE 0 /* has block scope via let/arraycomp */
|
||||||
#define JS_HAS_DESTRUCTURING 0 /* has [a,b] = ... or {p:a,q:b} = ... */
|
#define JS_HAS_DESTRUCTURING 0 /* has [a,b] = ... or {p:a,q:b} = ... */
|
||||||
|
@ -149,7 +113,6 @@
|
||||||
#define JS_HAS_CONST 1 /* has JS2 const as alternative var */
|
#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_FUN_EXPR_STMT 1 /* has function expression statement */
|
||||||
#define JS_HAS_NO_SUCH_METHOD 1 /* has o.__noSuchMethod__ handler */
|
#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_GENERATORS 1 /* has yield in generator function */
|
#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_BLOCK_SCOPE 1 /* has block scope via let/arraycomp */
|
||||||
#define JS_HAS_DESTRUCTURING 1 /* has [a,b] = ... or {p:a,q:b} = ... */
|
#define JS_HAS_DESTRUCTURING 1 /* has [a,b] = ... or {p:a,q:b} = ... */
|
||||||
|
@ -167,7 +130,6 @@
|
||||||
#define JS_HAS_CONST 1 /* has JS2 const as alternative var */
|
#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_FUN_EXPR_STMT 1 /* has function expression statement */
|
||||||
#define JS_HAS_NO_SUCH_METHOD 1 /* has o.__noSuchMethod__ handler */
|
#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_GENERATORS 1 /* has yield in generator function */
|
#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_BLOCK_SCOPE 1 /* has block scope via let/arraycomp */
|
||||||
#define JS_HAS_DESTRUCTURING 2 /* has [a,b] = ... or {p:a,q:b} = ... */
|
#define JS_HAS_DESTRUCTURING 2 /* has [a,b] = ... or {p:a,q:b} = ... */
|
||||||
|
|
|
@ -1,43 +1,9 @@
|
||||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||||
* vim: set ts=4 sw=4 et tw=99:
|
* vim: set ts=4 sw=4 et tw=99:
|
||||||
*
|
*
|
||||||
* ***** BEGIN LICENSE BLOCK *****
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
* 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/. */
|
||||||
* 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___
|
#ifndef jswrapper_h___
|
||||||
#define jswrapper_h___
|
#define jswrapper_h___
|
||||||
|
@ -51,30 +17,76 @@ namespace js {
|
||||||
|
|
||||||
class DummyFrameGuard;
|
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
|
* A wrapper is essentially a proxy that restricts access to certain traps. The
|
||||||
* want transparent forwarding behavior but don't want to use the derived
|
* way in which a wrapper restricts access to its traps depends on the
|
||||||
* traps and other baggage of js::Wrapper.
|
* particular policy for that wrapper. To allow a wrapper's policy to be
|
||||||
|
* customized, the Wrapper base class contains two functions, enter/leave, which
|
||||||
|
* are called as a policy enforcement check before/after each trap is forwarded.
|
||||||
|
*
|
||||||
|
* To minimize code duplication, a set of abstract wrapper classes is
|
||||||
|
* provided, from which other wrappers may inherit. These abstract classes are
|
||||||
|
* organized in the following hierarchy:
|
||||||
|
*
|
||||||
|
* BaseProxyHandler Wrapper
|
||||||
|
* | | |
|
||||||
|
* IndirectProxyHandler | |
|
||||||
|
* | | | |
|
||||||
|
* | IndirectWrapper |
|
||||||
|
* | |
|
||||||
|
* DirectProxyHandler |
|
||||||
|
* | |
|
||||||
|
* DirectWrapper
|
||||||
*/
|
*/
|
||||||
class JS_FRIEND_API(AbstractWrapper) : public ProxyHandler
|
class JS_FRIEND_API(Wrapper)
|
||||||
{
|
{
|
||||||
unsigned mFlags;
|
unsigned mFlags;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
unsigned flags() const { return mFlags; }
|
enum Action {
|
||||||
|
GET,
|
||||||
|
SET,
|
||||||
|
CALL,
|
||||||
|
PUNCTURE
|
||||||
|
};
|
||||||
|
|
||||||
explicit AbstractWrapper(unsigned flags);
|
enum Flags {
|
||||||
|
CROSS_COMPARTMENT = 1 << 0,
|
||||||
|
LAST_USED_FLAG = CROSS_COMPARTMENT
|
||||||
|
};
|
||||||
|
|
||||||
/* ES5 Harmony fundamental wrapper traps. */
|
typedef enum {
|
||||||
virtual bool getPropertyDescriptor(JSContext *cx, JSObject *wrapper, jsid id, bool set,
|
PermitObjectAccess,
|
||||||
PropertyDescriptor *desc) MOZ_OVERRIDE;
|
PermitPropertyAccess,
|
||||||
virtual bool getOwnPropertyDescriptor(JSContext *cx, JSObject *wrapper, jsid id, bool set,
|
DenyAccess
|
||||||
PropertyDescriptor *desc) MOZ_OVERRIDE;
|
} Permission;
|
||||||
virtual bool defineProperty(JSContext *cx, JSObject *wrapper, jsid id,
|
|
||||||
PropertyDescriptor *desc) MOZ_OVERRIDE;
|
static JSObject *New(JSContext *cx, JSObject *obj, JSObject *proto,
|
||||||
virtual bool getOwnPropertyNames(JSContext *cx, JSObject *wrapper, AutoIdVector &props) MOZ_OVERRIDE;
|
JSObject *parent, Wrapper *handler);
|
||||||
virtual bool delete_(JSContext *cx, JSObject *wrapper, jsid id, bool *bp) MOZ_OVERRIDE;
|
|
||||||
virtual bool enumerate(JSContext *cx, JSObject *wrapper, AutoIdVector &props) MOZ_OVERRIDE;
|
static Wrapper *wrapperHandler(const JSObject *wrapper);
|
||||||
virtual bool fix(JSContext *cx, JSObject *wrapper, Value *vp) MOZ_OVERRIDE;
|
|
||||||
|
static JSObject *wrappedObject(const JSObject *wrapper);
|
||||||
|
|
||||||
|
explicit Wrapper(unsigned flags);
|
||||||
|
|
||||||
|
unsigned flags() const {
|
||||||
|
return mFlags;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The function Wrapper::New takes a pointer to a Wrapper as the handler
|
||||||
|
* object. It then passes it on to the function NewProxyObject, which
|
||||||
|
* expects a pointer to a BaseProxyHandler as the handler object. We don't
|
||||||
|
* want to change Wrapper::New to take a pointer to a BaseProxyHandler,
|
||||||
|
* because that would allow the creation of wrappers with non-wrapper
|
||||||
|
* handlers. Unfortunately, we can't inherit Wrapper from BaseProxyHandler,
|
||||||
|
* since that would create a dreaded diamond, and we can't use dynamic_cast
|
||||||
|
* to cast Wrapper to BaseProxyHandler, since that would require us to
|
||||||
|
* compile with run time type information. Hence the need for this virtual
|
||||||
|
* function.
|
||||||
|
*/
|
||||||
|
virtual BaseProxyHandler *toBaseProxyHandler() = 0;
|
||||||
|
|
||||||
/* Policy enforcement traps.
|
/* Policy enforcement traps.
|
||||||
*
|
*
|
||||||
|
@ -82,12 +94,9 @@ class JS_FRIEND_API(AbstractWrapper) : public ProxyHandler
|
||||||
* on the underlying object's |id| property. In the case when |act| is CALL,
|
* on the underlying object's |id| property. In the case when |act| is CALL,
|
||||||
* |id| is generally JSID_VOID.
|
* |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,
|
* The |act| parameter to enter() specifies the action being performed. GET,
|
||||||
* SET, and CALL are self-explanatory, but PUNCTURE requires more explanation:
|
* SET, and CALL are self-explanatory, but PUNCTURE requires more
|
||||||
|
* explanation:
|
||||||
*
|
*
|
||||||
* GET and SET allow for a very fine-grained security membrane, through
|
* 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
|
* which access can be granted or denied on a per-property, per-object, and
|
||||||
|
@ -103,24 +112,87 @@ class JS_FRIEND_API(AbstractWrapper) : public ProxyHandler
|
||||||
* permission, and thus should generally be denied for security wrappers
|
* permission, and thus should generally be denied for security wrappers
|
||||||
* except under very special circumstances. When |act| is PUNCTURE, |id|
|
* except under very special circumstances. When |act| is PUNCTURE, |id|
|
||||||
* should be JSID_VOID.
|
* should be JSID_VOID.
|
||||||
* */
|
*/
|
||||||
enum Action { GET, SET, CALL, PUNCTURE };
|
virtual bool enter(JSContext *cx, JSObject *wrapper, jsid id, Action act,
|
||||||
virtual bool enter(JSContext *cx, JSObject *wrapper, jsid id, Action act, bool *bp);
|
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
|
* IndirectWrapper forwards its traps by forwarding them to
|
||||||
|
* IndirectProxyHandler. In effect, IndirectWrapper behaves the same as
|
||||||
|
* IndirectProxyHandler, except that it adds policy enforcement checks to each
|
||||||
|
* fundamental trap.
|
||||||
|
*/
|
||||||
|
class JS_FRIEND_API(IndirectWrapper) : public Wrapper,
|
||||||
|
public IndirectProxyHandler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit Wrapper(unsigned flags);
|
explicit IndirectWrapper(unsigned flags);
|
||||||
|
|
||||||
typedef enum { PermitObjectAccess, PermitPropertyAccess, DenyAccess } Permission;
|
virtual BaseProxyHandler* toBaseProxyHandler() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
virtual ~Wrapper();
|
virtual Wrapper *toWrapper() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
|
||||||
|
/* Spidermonkey extensions. */
|
||||||
|
virtual bool defaultValue(JSContext *cx, JSObject *wrapper_, JSType hint,
|
||||||
|
Value *vp) MOZ_OVERRIDE;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* DirectWrapper forwards its traps by forwarding them to DirectProxyHandler.
|
||||||
|
* In effect, DirectWrapper behaves the same as DirectProxyHandler, except that
|
||||||
|
* it adds policy enforcement checks to each trap.
|
||||||
|
*/
|
||||||
|
class JS_FRIEND_API(DirectWrapper) : public Wrapper, public DirectProxyHandler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit DirectWrapper(unsigned flags);
|
||||||
|
|
||||||
|
virtual ~DirectWrapper();
|
||||||
|
|
||||||
|
virtual BaseProxyHandler* toBaseProxyHandler() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual Wrapper *toWrapper() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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. */
|
/* ES5 Harmony derived wrapper traps. */
|
||||||
virtual bool has(JSContext *cx, JSObject *wrapper, jsid id, bool *bp) MOZ_OVERRIDE;
|
virtual bool has(JSContext *cx, JSObject *wrapper, jsid id, bool *bp) MOZ_OVERRIDE;
|
||||||
|
@ -136,36 +208,18 @@ class JS_FRIEND_API(Wrapper) : public AbstractWrapper
|
||||||
virtual bool construct(JSContext *cx, JSObject *wrapper, unsigned argc, Value *argv, Value *rval) 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 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 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 *obj_toString(JSContext *cx, JSObject *wrapper) MOZ_OVERRIDE;
|
||||||
virtual JSString *fun_toString(JSContext *cx, JSObject *wrapper, unsigned indent) 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,
|
||||||
virtual bool defaultValue(JSContext *cx, JSObject *wrapper, JSType hint, Value *vp) MOZ_OVERRIDE;
|
Value *vp) MOZ_OVERRIDE;
|
||||||
virtual bool iteratorNext(JSContext *cx, JSObject *wrapper, Value *vp) MOZ_OVERRIDE;
|
|
||||||
|
|
||||||
virtual void trace(JSTracer *trc, JSObject *wrapper) MOZ_OVERRIDE;
|
static DirectWrapper singleton;
|
||||||
|
|
||||||
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();
|
static void *getWrapperFamily();
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Base class for all cross compartment wrapper handlers. */
|
/* Base class for all cross compartment wrapper handlers. */
|
||||||
class JS_FRIEND_API(CrossCompartmentWrapper) : public Wrapper
|
class JS_FRIEND_API(CrossCompartmentWrapper) : public DirectWrapper
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CrossCompartmentWrapper(unsigned flags);
|
CrossCompartmentWrapper(unsigned flags);
|
||||||
|
@ -199,11 +253,10 @@ class JS_FRIEND_API(CrossCompartmentWrapper) : public Wrapper
|
||||||
virtual bool hasInstance(JSContext *cx, JSObject *wrapper, const Value *vp, bool *bp) 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 *obj_toString(JSContext *cx, JSObject *wrapper) MOZ_OVERRIDE;
|
||||||
virtual JSString *fun_toString(JSContext *cx, JSObject *wrapper, unsigned indent) 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 defaultValue(JSContext *cx, JSObject *wrapper, JSType hint, Value *vp) MOZ_OVERRIDE;
|
||||||
virtual bool iteratorNext(JSContext *cx, JSObject *wrapper, Value *vp);
|
virtual bool iteratorNext(JSContext *cx, JSObject *wrapper, Value *vp);
|
||||||
|
|
||||||
virtual void trace(JSTracer *trc, JSObject *wrapper) MOZ_OVERRIDE;
|
|
||||||
|
|
||||||
static CrossCompartmentWrapper singleton;
|
static CrossCompartmentWrapper singleton;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -227,7 +280,7 @@ class JS_FRIEND_API(SecurityWrapper) : public Base
|
||||||
virtual bool regexp_toShared(JSContext *cx, JSObject *proxy, RegExpGuard *g) MOZ_OVERRIDE;
|
virtual bool regexp_toShared(JSContext *cx, JSObject *proxy, RegExpGuard *g) MOZ_OVERRIDE;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef SecurityWrapper<Wrapper> SameCompartmentSecurityWrapper;
|
typedef SecurityWrapper<DirectWrapper> SameCompartmentSecurityWrapper;
|
||||||
typedef SecurityWrapper<CrossCompartmentWrapper> CrossCompartmentSecurityWrapper;
|
typedef SecurityWrapper<CrossCompartmentWrapper> CrossCompartmentSecurityWrapper;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -248,6 +301,43 @@ class JS_FRIEND_API(ForceFrame)
|
||||||
bool enter();
|
bool enter();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class JS_FRIEND_API(DeadObjectProxy) : public BaseProxyHandler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static int sDeadObjectFamily;
|
||||||
|
|
||||||
|
explicit DeadObjectProxy();
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
|
||||||
|
/* 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 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 bool getElementIfPresent(JSContext *cx, JSObject *obj, JSObject *receiver,
|
||||||
|
uint32_t index, Value *vp, bool *present);
|
||||||
|
|
||||||
|
|
||||||
|
static DeadObjectProxy singleton;
|
||||||
|
};
|
||||||
|
|
||||||
extern JSObject *
|
extern JSObject *
|
||||||
TransparentObjectWrapper(JSContext *cx, JSObject *obj, JSObject *wrappedProto, JSObject *parent,
|
TransparentObjectWrapper(JSContext *cx, JSObject *obj, JSObject *wrappedProto, JSObject *parent,
|
||||||
unsigned flags);
|
unsigned flags);
|
||||||
|
@ -266,20 +356,69 @@ IsWrapper(const JSObject *obj)
|
||||||
// stopAtOuter is true, then this returns the outer window if it was
|
// stopAtOuter is true, then this returns the outer window if it was
|
||||||
// previously wrapped. Otherwise, this returns the first object for
|
// previously wrapped. Otherwise, this returns the first object for
|
||||||
// which JSObject::isWrapper returns false.
|
// which JSObject::isWrapper returns false.
|
||||||
JS_FRIEND_API(JSObject *) UnwrapObject(JSObject *obj, bool stopAtOuter = true,
|
JS_FRIEND_API(JSObject *)
|
||||||
unsigned *flagsp = NULL);
|
UnwrapObject(JSObject *obj, bool stopAtOuter = true, unsigned *flagsp = NULL);
|
||||||
|
|
||||||
// Given a JSObject, returns that object stripped of wrappers. At each stage,
|
// Given a JSObject, returns that object stripped of wrappers. At each stage,
|
||||||
// the security wrapper has the opportunity to veto the unwrap. Since checked
|
// the security wrapper has the opportunity to veto the unwrap. Since checked
|
||||||
// code should never be unwrapping outer window wrappers, we always stop at
|
// code should never be unwrapping outer window wrappers, we always stop at
|
||||||
// outer windows.
|
// outer windows.
|
||||||
JS_FRIEND_API(JSObject *) UnwrapObjectChecked(JSContext *cx, JSObject *obj);
|
JS_FRIEND_API(JSObject *)
|
||||||
|
UnwrapObjectChecked(JSContext *cx, JSObject *obj);
|
||||||
|
|
||||||
bool IsCrossCompartmentWrapper(const JSObject *obj);
|
JS_FRIEND_API(bool)
|
||||||
|
IsCrossCompartmentWrapper(const JSObject *obj);
|
||||||
|
|
||||||
|
JSObject *
|
||||||
|
NewDeadProxyObject(JSContext *cx, JSObject *parent);
|
||||||
|
|
||||||
void
|
void
|
||||||
NukeCrossCompartmentWrapper(JSObject *wrapper);
|
NukeCrossCompartmentWrapper(JSObject *wrapper);
|
||||||
|
|
||||||
|
bool
|
||||||
|
RemapWrapper(JSContext *cx, JSObject *wobj, JSObject *newTarget);
|
||||||
|
|
||||||
|
JS_FRIEND_API(bool)
|
||||||
|
RemapAllWrappersForObject(JSContext *cx, JSObject *oldTarget,
|
||||||
|
JSObject *newTarget);
|
||||||
|
|
||||||
|
// API to recompute all cross-compartment wrappers whose source and target
|
||||||
|
// match the given filters.
|
||||||
|
//
|
||||||
|
// These filters are designed to be ephemeral stack classes, and thus don't
|
||||||
|
// do any rooting or holding of their members.
|
||||||
|
struct CompartmentFilter {
|
||||||
|
virtual bool match(JSCompartment *c) const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct AllCompartments : public CompartmentFilter {
|
||||||
|
virtual bool match(JSCompartment *c) const { return true; }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ContentCompartmentsOnly : public CompartmentFilter {
|
||||||
|
virtual bool match(JSCompartment *c) const {
|
||||||
|
return !IsSystemCompartment(c);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SingleCompartment : public CompartmentFilter {
|
||||||
|
JSCompartment *ours;
|
||||||
|
SingleCompartment(JSCompartment *c) : ours(c) {}
|
||||||
|
virtual bool match(JSCompartment *c) const { return c == ours; }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CompartmentsWithPrincipals : public CompartmentFilter {
|
||||||
|
JSPrincipals *principals;
|
||||||
|
CompartmentsWithPrincipals(JSPrincipals *p) : principals(p) {}
|
||||||
|
virtual bool match(JSCompartment *c) const {
|
||||||
|
return JS_GetCompartmentPrincipals(c) == principals;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
JS_FRIEND_API(bool)
|
||||||
|
RecomputeWrappers(JSContext *cx, const CompartmentFilter &sourceFilter,
|
||||||
|
const CompartmentFilter &targetFilter);
|
||||||
|
|
||||||
} /* namespace js */
|
} /* namespace js */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,215 +0,0 @@
|
||||||
/* -*- 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 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 jsxdrapi_h___
|
|
||||||
#define jsxdrapi_h___
|
|
||||||
|
|
||||||
/*
|
|
||||||
* JS external data representation interface API.
|
|
||||||
*
|
|
||||||
* The XDR system is comprised of three major parts:
|
|
||||||
*
|
|
||||||
* - the state serialization/deserialization APIs, which allow consumers
|
|
||||||
* of the API to serialize JS runtime state (script bytecodes, atom maps,
|
|
||||||
* object graphs, etc.) for later restoration. These portions
|
|
||||||
* are implemented in various appropriate files, such as jsscript.c
|
|
||||||
* for the script portions and jsobj.c for object state.
|
|
||||||
* - the callback APIs through which the runtime requests an opaque
|
|
||||||
* representation of a native object, and through which the runtime
|
|
||||||
* constructs a live native object from an opaque representation. These
|
|
||||||
* portions are the responsibility of the native object implementor.
|
|
||||||
* - utility functions for en/decoding of primitive types, such as
|
|
||||||
* JSStrings. This portion is implemented in jsxdrapi.c.
|
|
||||||
*
|
|
||||||
* Spiritually guided by Sun's XDR, where appropriate.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "jspubtd.h"
|
|
||||||
#include "jsprvtd.h"
|
|
||||||
|
|
||||||
JS_BEGIN_EXTERN_C
|
|
||||||
|
|
||||||
/* We use little-endian byteorder for all encoded data */
|
|
||||||
|
|
||||||
#if defined IS_LITTLE_ENDIAN
|
|
||||||
#define JSXDR_SWAB32(x) x
|
|
||||||
#define JSXDR_SWAB16(x) x
|
|
||||||
#elif defined IS_BIG_ENDIAN
|
|
||||||
#define JSXDR_SWAB32(x) (((uint32_t)(x) >> 24) | \
|
|
||||||
(((uint32_t)(x) >> 8) & 0xff00) | \
|
|
||||||
(((uint32_t)(x) << 8) & 0xff0000) | \
|
|
||||||
((uint32_t)(x) << 24))
|
|
||||||
#define JSXDR_SWAB16(x) (((uint16_t)(x) >> 8) | ((uint16_t)(x) << 8))
|
|
||||||
#else
|
|
||||||
#error "unknown byte order"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define JSXDR_ALIGN 4
|
|
||||||
|
|
||||||
typedef enum JSXDRMode {
|
|
||||||
JSXDR_ENCODE,
|
|
||||||
JSXDR_DECODE
|
|
||||||
} JSXDRMode;
|
|
||||||
|
|
||||||
typedef enum JSXDRWhence {
|
|
||||||
JSXDR_SEEK_SET,
|
|
||||||
JSXDR_SEEK_CUR,
|
|
||||||
JSXDR_SEEK_END
|
|
||||||
} JSXDRWhence;
|
|
||||||
|
|
||||||
typedef struct JSXDROps {
|
|
||||||
JSBool (*get32)(JSXDRState *, uint32_t *);
|
|
||||||
JSBool (*set32)(JSXDRState *, uint32_t *);
|
|
||||||
JSBool (*getbytes)(JSXDRState *, char *, uint32_t);
|
|
||||||
JSBool (*setbytes)(JSXDRState *, char *, uint32_t);
|
|
||||||
void * (*raw)(JSXDRState *, uint32_t);
|
|
||||||
JSBool (*seek)(JSXDRState *, int32_t, JSXDRWhence);
|
|
||||||
uint32_t (*tell)(JSXDRState *);
|
|
||||||
void (*finalize)(JSXDRState *);
|
|
||||||
} JSXDROps;
|
|
||||||
|
|
||||||
struct JSXDRState {
|
|
||||||
JSXDRMode mode;
|
|
||||||
JSXDROps *ops;
|
|
||||||
JSContext *cx;
|
|
||||||
void *userdata;
|
|
||||||
const char *sharedFilename;
|
|
||||||
JSPrincipals *principals;
|
|
||||||
JSPrincipals *originPrincipals;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern JS_PUBLIC_API(void)
|
|
||||||
JS_XDRInitBase(JSXDRState *xdr, JSXDRMode mode, JSContext *cx);
|
|
||||||
|
|
||||||
extern JS_PUBLIC_API(JSXDRState *)
|
|
||||||
JS_XDRNewMem(JSContext *cx, JSXDRMode mode);
|
|
||||||
|
|
||||||
extern JS_PUBLIC_API(void *)
|
|
||||||
JS_XDRMemGetData(JSXDRState *xdr, uint32_t *lp);
|
|
||||||
|
|
||||||
extern JS_PUBLIC_API(void)
|
|
||||||
JS_XDRMemSetData(JSXDRState *xdr, void *data, uint32_t len);
|
|
||||||
|
|
||||||
extern JS_PUBLIC_API(uint32_t)
|
|
||||||
JS_XDRMemDataLeft(JSXDRState *xdr);
|
|
||||||
|
|
||||||
extern JS_PUBLIC_API(void)
|
|
||||||
JS_XDRMemResetData(JSXDRState *xdr);
|
|
||||||
|
|
||||||
extern JS_PUBLIC_API(void)
|
|
||||||
JS_XDRDestroy(JSXDRState *xdr);
|
|
||||||
|
|
||||||
extern JS_PUBLIC_API(JSBool)
|
|
||||||
JS_XDRUint8(JSXDRState *xdr, uint8_t *b);
|
|
||||||
|
|
||||||
extern JS_PUBLIC_API(JSBool)
|
|
||||||
JS_XDRUint16(JSXDRState *xdr, uint16_t *s);
|
|
||||||
|
|
||||||
extern JS_PUBLIC_API(JSBool)
|
|
||||||
JS_XDRUint32(JSXDRState *xdr, uint32_t *lp);
|
|
||||||
|
|
||||||
extern JS_PUBLIC_API(JSBool)
|
|
||||||
JS_XDRBytes(JSXDRState *xdr, char *bytes, uint32_t len);
|
|
||||||
|
|
||||||
extern JS_PUBLIC_API(JSBool)
|
|
||||||
JS_XDRCString(JSXDRState *xdr, char **sp);
|
|
||||||
|
|
||||||
extern JS_PUBLIC_API(JSBool)
|
|
||||||
JS_XDRString(JSXDRState *xdr, JSString **strp);
|
|
||||||
|
|
||||||
extern JS_PUBLIC_API(JSBool)
|
|
||||||
JS_XDRStringOrNull(JSXDRState *xdr, JSString **strp);
|
|
||||||
|
|
||||||
extern JS_PUBLIC_API(JSBool)
|
|
||||||
JS_XDRDouble(JSXDRState *xdr, double *dp);
|
|
||||||
|
|
||||||
extern JS_PUBLIC_API(JSBool)
|
|
||||||
JS_XDRFunctionObject(JSXDRState *xdr, JSObject **objp);
|
|
||||||
|
|
||||||
extern JS_PUBLIC_API(JSBool)
|
|
||||||
JS_XDRScript(JSXDRState *xdr, JSScript **scriptp);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Magic numbers.
|
|
||||||
*/
|
|
||||||
#define JSXDR_MAGIC_SCRIPT_1 0xdead0001
|
|
||||||
#define JSXDR_MAGIC_SCRIPT_2 0xdead0002
|
|
||||||
#define JSXDR_MAGIC_SCRIPT_3 0xdead0003
|
|
||||||
#define JSXDR_MAGIC_SCRIPT_4 0xdead0004
|
|
||||||
#define JSXDR_MAGIC_SCRIPT_5 0xdead0005
|
|
||||||
#define JSXDR_MAGIC_SCRIPT_6 0xdead0006
|
|
||||||
#define JSXDR_MAGIC_SCRIPT_7 0xdead0007
|
|
||||||
#define JSXDR_MAGIC_SCRIPT_8 0xdead0008
|
|
||||||
#define JSXDR_MAGIC_SCRIPT_9 0xdead0009
|
|
||||||
#define JSXDR_MAGIC_SCRIPT_10 0xdead000a
|
|
||||||
#define JSXDR_MAGIC_SCRIPT_11 0xdead000b
|
|
||||||
#define JSXDR_MAGIC_SCRIPT_12 0xdead000c
|
|
||||||
#define JSXDR_MAGIC_SCRIPT_CURRENT JSXDR_MAGIC_SCRIPT_12
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Bytecode version number. Increment the subtrahend whenever JS bytecode
|
|
||||||
* changes incompatibly.
|
|
||||||
*
|
|
||||||
* This version number is XDR'd near the front of xdr bytecode and
|
|
||||||
* aborts deserialization if there is a mismatch between the current
|
|
||||||
* and saved versions. If deserialization fails, the data should be
|
|
||||||
* invalidated if possible.
|
|
||||||
*/
|
|
||||||
#define JSXDR_BYTECODE_VERSION (0xb973c0de - 109)
|
|
||||||
|
|
||||||
JS_END_EXTERN_C
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Library-private functions.
|
|
||||||
*/
|
|
||||||
extern JSBool
|
|
||||||
js_XDRAtom(JSXDRState *xdr, JSAtom **atomp);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Set principals that should be assigned to decoded scripts and functions.
|
|
||||||
* The principals is not held via JS_HoldPrincipals/JS_DropPrincipals unless
|
|
||||||
* they are stored in a decoded script. Thus the caller must either ensure
|
|
||||||
* that principal outlive the XDR instance or are explicitly set to NULL
|
|
||||||
* before they release by the caller.
|
|
||||||
*/
|
|
||||||
extern void
|
|
||||||
js_XDRSetPrincipals(JSXDRState *xdr, JSPrincipals *principals, JSPrincipals *originPrincipals);
|
|
||||||
|
|
||||||
#endif /* ! jsxdrapi_h___ */
|
|
|
@ -1,42 +1,7 @@
|
||||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
/* -*- 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
|
||||||
* ***** BEGIN LICENSE BLOCK *****
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
* 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++. */
|
/* Implementations of runtime and static assertion macros for C and C++. */
|
||||||
|
|
||||||
|
@ -44,11 +9,27 @@
|
||||||
#define mozilla_Assertions_h_
|
#define mozilla_Assertions_h_
|
||||||
|
|
||||||
#include "mozilla/Attributes.h"
|
#include "mozilla/Attributes.h"
|
||||||
#include "mozilla/Types.h"
|
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#ifndef WIN32
|
#ifdef WIN32
|
||||||
|
/*
|
||||||
|
* TerminateProcess and GetCurrentProcess are defined in <winbase.h>, which
|
||||||
|
* further depends on <windef.h>. We hardcode these few definitions manually
|
||||||
|
* because those headers clutter the global namespace with a significant
|
||||||
|
* number of undesired macros and symbols.
|
||||||
|
*/
|
||||||
|
# ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
# endif
|
||||||
|
__declspec(dllimport) int __stdcall
|
||||||
|
TerminateProcess(void* hProcess, unsigned int uExitCode);
|
||||||
|
__declspec(dllimport) void* __stdcall GetCurrentProcess(void);
|
||||||
|
# ifdef __cplusplus
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
#else
|
||||||
# include <signal.h>
|
# include <signal.h>
|
||||||
#endif
|
#endif
|
||||||
#ifdef ANDROID
|
#ifdef ANDROID
|
||||||
|
@ -140,58 +121,73 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(WIN32)
|
/*
|
||||||
|
* MOZ_CRASH crashes the program, plain and simple, in a Breakpad-compatible
|
||||||
|
* way, in both debug and release builds.
|
||||||
|
*
|
||||||
|
* MOZ_CRASH is a good solution for "handling" failure cases when you're
|
||||||
|
* unwilling or unable to handle them more cleanly -- for OOM, for likely memory
|
||||||
|
* corruption, and so on. It's also a good solution if you need safe behavior
|
||||||
|
* in release builds as well as debug builds. But if the failure is one that
|
||||||
|
* should be debugged and fixed, MOZ_ASSERT is generally preferable.
|
||||||
|
*/
|
||||||
|
#if defined(_MSC_VER)
|
||||||
/*
|
/*
|
||||||
* We used to call DebugBreak() on Windows, but amazingly, it causes
|
* On MSVC use the __debugbreak compiler intrinsic, which produces an inline
|
||||||
* the MSVS 2010 debugger not to be able to recover a call stack.
|
* (not nested in a system function) breakpoint. This distinctively invokes
|
||||||
*/
|
* Breakpad without requiring system library symbols on all stack-processing
|
||||||
# define MOZ_CRASH() \
|
* machines, as a nested breakpoint would require. We use TerminateProcess
|
||||||
do { \
|
* with the exit code aborting would generate because we don't want to invoke
|
||||||
*((volatile int *) NULL) = 123; \
|
* atexit handlers, destructors, library unload handlers, and so on when our
|
||||||
exit(3); \
|
* process might be in a compromised state. We don't use abort() because
|
||||||
} while (0)
|
* it'd cause Windows to annoyingly pop up the process error dialog multiple
|
||||||
#elif defined(ANDROID)
|
* times. See bug 345118 and bug 426163.
|
||||||
/*
|
*
|
||||||
* On Android, raise(SIGABRT) is handled asynchronously. Seg fault now
|
* (Technically these are Windows requirements, not MSVC requirements. But
|
||||||
* so we crash immediately and capture the current call stack. We need
|
* practically you need MSVC for debugging, and we only ship builds created
|
||||||
* to specifically use the global namespace in the C++ case.
|
* by MSVC, so doing it this way reduces complexity.)
|
||||||
*/
|
*/
|
||||||
# ifdef __cplusplus
|
# ifdef __cplusplus
|
||||||
# define MOZ_CRASH() \
|
# define MOZ_CRASH() \
|
||||||
do { \
|
do { \
|
||||||
*((volatile int *) NULL) = 123; \
|
__debugbreak(); \
|
||||||
|
*((volatile int*) NULL) = 123; \
|
||||||
|
::TerminateProcess(::GetCurrentProcess(), 3); \
|
||||||
|
} while (0)
|
||||||
|
# else
|
||||||
|
# define MOZ_CRASH() \
|
||||||
|
do { \
|
||||||
|
__debugbreak(); \
|
||||||
|
*((volatile int*) NULL) = 123; \
|
||||||
|
TerminateProcess(GetCurrentProcess(), 3); \
|
||||||
|
} while (0)
|
||||||
|
# endif
|
||||||
|
#else
|
||||||
|
# ifdef __cplusplus
|
||||||
|
# define MOZ_CRASH() \
|
||||||
|
do { \
|
||||||
|
*((volatile int*) NULL) = 123; \
|
||||||
::abort(); \
|
::abort(); \
|
||||||
} while (0)
|
} while (0)
|
||||||
# else
|
# else
|
||||||
# define MOZ_CRASH() \
|
# define MOZ_CRASH() \
|
||||||
do { \
|
do { \
|
||||||
*((volatile int *) NULL) = 123; \
|
*((volatile int*) NULL) = 123; \
|
||||||
abort(); \
|
abort(); \
|
||||||
} while (0)
|
} while (0)
|
||||||
# endif
|
# 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
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
extern MFBT_API(void)
|
* Prints |s| as an assertion failure (using file and ln as the location of the
|
||||||
MOZ_Assert(const char* s, const char* file, int ln);
|
* assertion) to the standard debug-output channel.
|
||||||
|
*
|
||||||
|
* Usually you should use MOZ_ASSERT instead of this method. This method is
|
||||||
|
* primarily for internal use in this header, and only secondarily for use in
|
||||||
|
* implementing release-build assertions.
|
||||||
|
*/
|
||||||
static MOZ_ALWAYS_INLINE void
|
static MOZ_ALWAYS_INLINE void
|
||||||
MOZ_OutputAssertMessage(const char* s, const char *file, int ln)
|
MOZ_ReportAssertionFailure(const char* s, const char* file, int ln)
|
||||||
{
|
{
|
||||||
#ifdef ANDROID
|
#ifdef ANDROID
|
||||||
__android_log_print(ANDROID_LOG_FATAL, "MOZ_Assert",
|
__android_log_print(ANDROID_LOG_FATAL, "MOZ_Assert",
|
||||||
|
@ -243,7 +239,7 @@ MOZ_OutputAssertMessage(const char* s, const char *file, int ln)
|
||||||
# define MOZ_ASSERT_HELPER1(expr) \
|
# define MOZ_ASSERT_HELPER1(expr) \
|
||||||
do { \
|
do { \
|
||||||
if (!(expr)) { \
|
if (!(expr)) { \
|
||||||
MOZ_OutputAssertMessage(#expr, __FILE__, __LINE__); \
|
MOZ_ReportAssertionFailure(#expr, __FILE__, __LINE__); \
|
||||||
MOZ_CRASH(); \
|
MOZ_CRASH(); \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
@ -251,7 +247,7 @@ MOZ_OutputAssertMessage(const char* s, const char *file, int ln)
|
||||||
# define MOZ_ASSERT_HELPER2(expr, explain) \
|
# define MOZ_ASSERT_HELPER2(expr, explain) \
|
||||||
do { \
|
do { \
|
||||||
if (!(expr)) { \
|
if (!(expr)) { \
|
||||||
MOZ_OutputAssertMessage(#expr " (" explain ")", __FILE__, __LINE__); \
|
MOZ_ReportAssertionFailure(#expr " (" explain ")", __FILE__, __LINE__); \
|
||||||
MOZ_CRASH(); \
|
MOZ_CRASH(); \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
@ -302,19 +298,38 @@ MOZ_OutputAssertMessage(const char* s, const char *file, int ln)
|
||||||
# define MOZ_ASSERT_IF(cond, expr) do { } while (0)
|
# define MOZ_ASSERT_IF(cond, expr) do { } while (0)
|
||||||
#endif
|
#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
|
* MOZ_NOT_REACHED_MARKER() expands to an expression which states that it is
|
||||||
* reach this point. Most code should probably use the higher level
|
* undefined behavior for execution to reach this point. No guarantees are made
|
||||||
* MOZ_NOT_REACHED (which expands to this when appropriate).
|
* about what will happen if this is reached at runtime. Most code should
|
||||||
|
* probably use the higher level MOZ_NOT_REACHED, which uses this when
|
||||||
|
* appropriate.
|
||||||
*/
|
*/
|
||||||
#if defined(__clang__)
|
#if defined(__clang__)
|
||||||
# define MOZ_NOT_REACHED_MARKER() __builtin_unreachable()
|
# define MOZ_NOT_REACHED_MARKER() __builtin_unreachable()
|
||||||
#elif defined(__GNUC__)
|
#elif defined(__GNUC__)
|
||||||
|
/*
|
||||||
|
* __builtin_unreachable() was implemented in gcc 4.5. If we don't have
|
||||||
|
* that, call a noreturn function; abort() will do nicely. Qualify the call
|
||||||
|
* in C++ in case there's another abort() visible in local scope.
|
||||||
|
*/
|
||||||
# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
|
# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
|
||||||
# define MOZ_NOT_REACHED_MARKER() __builtin_unreachable()
|
# define MOZ_NOT_REACHED_MARKER() __builtin_unreachable()
|
||||||
|
# else
|
||||||
|
# ifdef __cplusplus
|
||||||
|
# define MOZ_NOT_REACHED_MARKER() ::abort()
|
||||||
|
# else
|
||||||
|
# define MOZ_NOT_REACHED_MARKER() abort()
|
||||||
|
# endif
|
||||||
# endif
|
# endif
|
||||||
#elif defined(_MSC_VER)
|
#elif defined(_MSC_VER)
|
||||||
# define MOZ_NOT_REACHED_MARKER() __assume(0)
|
# define MOZ_NOT_REACHED_MARKER() __assume(0)
|
||||||
|
#else
|
||||||
|
# ifdef __cplusplus
|
||||||
|
# define MOZ_NOT_REACHED_MARKER() ::abort()
|
||||||
|
# else
|
||||||
|
# define MOZ_NOT_REACHED_MARKER() abort()
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -334,39 +349,14 @@ MOZ_OutputAssertMessage(const char* s, const char *file, int ln)
|
||||||
* MOZ_NOT_REACHED("boolean literal that's not true or false?");
|
* MOZ_NOT_REACHED("boolean literal that's not true or false?");
|
||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
#if defined(MOZ_NOT_REACHED_MARKER)
|
#if defined(DEBUG)
|
||||||
# if defined(DEBUG)
|
# define MOZ_NOT_REACHED(reason) \
|
||||||
# define MOZ_NOT_REACHED(reason) do { \
|
do { \
|
||||||
MOZ_Assert(reason, __FILE__, __LINE__); \
|
MOZ_ASSERT(false, reason); \
|
||||||
MOZ_NOT_REACHED_MARKER(); \
|
MOZ_NOT_REACHED_MARKER(); \
|
||||||
} while (0)
|
} while (0)
|
||||||
# else
|
|
||||||
# define MOZ_NOT_REACHED(reason) MOZ_NOT_REACHED_MARKER()
|
|
||||||
# endif
|
|
||||||
#else
|
#else
|
||||||
# if defined(__GNUC__)
|
# define MOZ_NOT_REACHED(reason) MOZ_NOT_REACHED_MARKER()
|
||||||
/*
|
|
||||||
* 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
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -1,42 +1,7 @@
|
||||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
/* -*- 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
|
||||||
* ***** BEGIN LICENSE BLOCK *****
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
* 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. */
|
/* Implementations of various class and method modifier attributes. */
|
||||||
|
|
||||||
|
@ -180,6 +145,19 @@
|
||||||
# define MOZ_NORETURN /* no support */
|
# define MOZ_NORETURN /* no support */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* MOZ_ASAN_BLACKLIST is a macro to tell AddressSanitizer (a compile-time
|
||||||
|
* instrumentation shipped with Clang) to not instrument the annotated function.
|
||||||
|
* Furthermore, it will prevent the compiler from inlining the function because
|
||||||
|
* inlining currently breaks the blacklisting mechanism of AddressSanitizer.
|
||||||
|
*/
|
||||||
|
#if defined(MOZ_ASAN)
|
||||||
|
# define MOZ_ASAN_BLACKLIST MOZ_NEVER_INLINE __attribute__((no_address_safety_analysis))
|
||||||
|
# else
|
||||||
|
# define MOZ_ASAN_BLACKLIST
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
/* -*- 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
|
/* 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,
|
* 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/. */
|
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
@ -52,7 +52,8 @@ namespace mozilla {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
template<unsigned KeySize, class T>
|
template<unsigned KeySize, class T>
|
||||||
class BloomFilter {
|
class BloomFilter
|
||||||
|
{
|
||||||
/*
|
/*
|
||||||
* A counting Bloom filter with 8-bit counters. For now we assume
|
* A counting Bloom filter with 8-bit counters. For now we assume
|
||||||
* that having two hash functions is enough, but we may revisit that
|
* that having two hash functions is enough, but we may revisit that
|
||||||
|
@ -101,7 +102,7 @@ class BloomFilter {
|
||||||
* positive rate for N == 100 and to quite bad false positive
|
* positive rate for N == 100 and to quite bad false positive
|
||||||
* rates for larger N.
|
* rates for larger N.
|
||||||
*/
|
*/
|
||||||
public:
|
public:
|
||||||
BloomFilter() {
|
BloomFilter() {
|
||||||
MOZ_STATIC_ASSERT(KeySize <= keyShift, "KeySize too big");
|
MOZ_STATIC_ASSERT(KeySize <= keyShift, "KeySize too big");
|
||||||
|
|
||||||
|
@ -142,7 +143,7 @@ public:
|
||||||
void remove(uint32_t hash);
|
void remove(uint32_t hash);
|
||||||
bool mightContain(uint32_t hash) const;
|
bool mightContain(uint32_t hash) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static const size_t arraySize = (1 << KeySize);
|
static const size_t arraySize = (1 << KeySize);
|
||||||
static const uint32_t keyMask = (1 << KeySize) - 1;
|
static const uint32_t keyMask = (1 << KeySize) - 1;
|
||||||
static const uint32_t keyShift = 16;
|
static const uint32_t keyShift = 16;
|
||||||
|
@ -164,67 +165,67 @@ template<unsigned KeySize, class T>
|
||||||
inline void
|
inline void
|
||||||
BloomFilter<KeySize, T>::clear()
|
BloomFilter<KeySize, T>::clear()
|
||||||
{
|
{
|
||||||
memset(counters, 0, arraySize);
|
memset(counters, 0, arraySize);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<unsigned KeySize, class T>
|
template<unsigned KeySize, class T>
|
||||||
inline void
|
inline void
|
||||||
BloomFilter<KeySize, T>::add(uint32_t hash)
|
BloomFilter<KeySize, T>::add(uint32_t hash)
|
||||||
{
|
{
|
||||||
uint8_t& slot1 = firstSlot(hash);
|
uint8_t& slot1 = firstSlot(hash);
|
||||||
if (MOZ_LIKELY(!full(slot1)))
|
if (MOZ_LIKELY(!full(slot1)))
|
||||||
++slot1;
|
++slot1;
|
||||||
|
|
||||||
uint8_t& slot2 = secondSlot(hash);
|
uint8_t& slot2 = secondSlot(hash);
|
||||||
if (MOZ_LIKELY(!full(slot2)))
|
if (MOZ_LIKELY(!full(slot2)))
|
||||||
++slot2;
|
++slot2;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<unsigned KeySize, class T>
|
template<unsigned KeySize, class T>
|
||||||
MOZ_ALWAYS_INLINE void
|
MOZ_ALWAYS_INLINE void
|
||||||
BloomFilter<KeySize, T>::add(const T* t)
|
BloomFilter<KeySize, T>::add(const T* t)
|
||||||
{
|
{
|
||||||
uint32_t hash = t->hash();
|
uint32_t hash = t->hash();
|
||||||
return add(hash);
|
return add(hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<unsigned KeySize, class T>
|
template<unsigned KeySize, class T>
|
||||||
inline void
|
inline void
|
||||||
BloomFilter<KeySize, T>::remove(uint32_t hash)
|
BloomFilter<KeySize, T>::remove(uint32_t hash)
|
||||||
{
|
{
|
||||||
// If the slots are full, we don't know whether we bumped them to be
|
// 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.
|
// there when we added or not, so just leave them full.
|
||||||
uint8_t& slot1 = firstSlot(hash);
|
uint8_t& slot1 = firstSlot(hash);
|
||||||
if (MOZ_LIKELY(!full(slot1)))
|
if (MOZ_LIKELY(!full(slot1)))
|
||||||
--slot1;
|
--slot1;
|
||||||
|
|
||||||
uint8_t& slot2 = secondSlot(hash);
|
uint8_t& slot2 = secondSlot(hash);
|
||||||
if (MOZ_LIKELY(!full(slot2)))
|
if (MOZ_LIKELY(!full(slot2)))
|
||||||
--slot2;
|
--slot2;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<unsigned KeySize, class T>
|
template<unsigned KeySize, class T>
|
||||||
MOZ_ALWAYS_INLINE void
|
MOZ_ALWAYS_INLINE void
|
||||||
BloomFilter<KeySize, T>::remove(const T* t)
|
BloomFilter<KeySize, T>::remove(const T* t)
|
||||||
{
|
{
|
||||||
uint32_t hash = t->hash();
|
uint32_t hash = t->hash();
|
||||||
remove(hash);
|
remove(hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<unsigned KeySize, class T>
|
template<unsigned KeySize, class T>
|
||||||
MOZ_ALWAYS_INLINE bool
|
MOZ_ALWAYS_INLINE bool
|
||||||
BloomFilter<KeySize, T>::mightContain(uint32_t hash) const
|
BloomFilter<KeySize, T>::mightContain(uint32_t hash) const
|
||||||
{
|
{
|
||||||
// Check that all the slots for this hash contain something
|
// Check that all the slots for this hash contain something
|
||||||
return firstSlot(hash) && secondSlot(hash);
|
return firstSlot(hash) && secondSlot(hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<unsigned KeySize, class T>
|
template<unsigned KeySize, class T>
|
||||||
MOZ_ALWAYS_INLINE bool
|
MOZ_ALWAYS_INLINE bool
|
||||||
BloomFilter<KeySize, T>::mightContain(const T* t) const
|
BloomFilter<KeySize, T>::mightContain(const T* t) const
|
||||||
{
|
{
|
||||||
uint32_t hash = t->hash();
|
uint32_t hash = t->hash();
|
||||||
return mightContain(hash);
|
return mightContain(hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
|
@ -0,0 +1,809 @@
|
||||||
|
/* -*- 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/. */
|
||||||
|
|
||||||
|
/* Provides checked integers, detecting integer overflow and divide-by-0. */
|
||||||
|
|
||||||
|
#ifndef mozilla_CheckedInt_h_
|
||||||
|
#define mozilla_CheckedInt_h_
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Build options. Comment out these #defines to disable the corresponding
|
||||||
|
* optional feature. Disabling features may be useful for code using
|
||||||
|
* CheckedInt outside of Mozilla (e.g. WebKit)
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Enable usage of MOZ_STATIC_ASSERT to check for unsupported types.
|
||||||
|
// If disabled, static asserts are replaced by regular assert().
|
||||||
|
#define MOZ_CHECKEDINT_ENABLE_MOZ_ASSERTS
|
||||||
|
|
||||||
|
/*
|
||||||
|
* End of build options
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef MOZ_CHECKEDINT_ENABLE_MOZ_ASSERTS
|
||||||
|
# include "mozilla/Assertions.h"
|
||||||
|
#else
|
||||||
|
# ifndef MOZ_STATIC_ASSERT
|
||||||
|
# include <cassert>
|
||||||
|
# define MOZ_STATIC_ASSERT(cond, reason) assert((cond) && reason)
|
||||||
|
# define MOZ_ASSERT(cond, reason) assert((cond) && reason)
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "mozilla/StandardInteger.h"
|
||||||
|
|
||||||
|
#include <climits>
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Step 1: manually record supported types
|
||||||
|
*
|
||||||
|
* What's nontrivial here is that there are different families of integer
|
||||||
|
* types: basic integer types and stdint types. It is merrily undefined which
|
||||||
|
* types from one family may be just typedefs for a type from another family.
|
||||||
|
*
|
||||||
|
* For example, on GCC 4.6, aside from the basic integer types, the only other
|
||||||
|
* type that isn't just a typedef for some of them, is int8_t.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct UnsupportedType {};
|
||||||
|
|
||||||
|
template<typename IntegerType>
|
||||||
|
struct IsSupportedPass2
|
||||||
|
{
|
||||||
|
static const bool value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename IntegerType>
|
||||||
|
struct IsSupported
|
||||||
|
{
|
||||||
|
static const bool value = IsSupportedPass2<IntegerType>::value;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct IsSupported<int8_t>
|
||||||
|
{ static const bool value = true; };
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct IsSupported<uint8_t>
|
||||||
|
{ static const bool value = true; };
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct IsSupported<int16_t>
|
||||||
|
{ static const bool value = true; };
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct IsSupported<uint16_t>
|
||||||
|
{ static const bool value = true; };
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct IsSupported<int32_t>
|
||||||
|
{ static const bool value = true; };
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct IsSupported<uint32_t>
|
||||||
|
{ static const bool value = true; };
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct IsSupported<int64_t>
|
||||||
|
{ static const bool value = true; };
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct IsSupported<uint64_t>
|
||||||
|
{ static const bool value = true; };
|
||||||
|
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct IsSupportedPass2<char>
|
||||||
|
{ static const bool value = true; };
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct IsSupportedPass2<unsigned char>
|
||||||
|
{ static const bool value = true; };
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct IsSupportedPass2<short>
|
||||||
|
{ static const bool value = true; };
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct IsSupportedPass2<unsigned short>
|
||||||
|
{ static const bool value = true; };
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct IsSupportedPass2<int>
|
||||||
|
{ static const bool value = true; };
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct IsSupportedPass2<unsigned int>
|
||||||
|
{ static const bool value = true; };
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct IsSupportedPass2<long>
|
||||||
|
{ static const bool value = true; };
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct IsSupportedPass2<unsigned long>
|
||||||
|
{ static const bool value = true; };
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Step 2: some integer-traits kind of stuff.
|
||||||
|
*/
|
||||||
|
|
||||||
|
template<size_t Size, bool Signedness>
|
||||||
|
struct StdintTypeForSizeAndSignedness
|
||||||
|
{};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct StdintTypeForSizeAndSignedness<1, true>
|
||||||
|
{ typedef int8_t Type; };
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct StdintTypeForSizeAndSignedness<1, false>
|
||||||
|
{ typedef uint8_t Type; };
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct StdintTypeForSizeAndSignedness<2, true>
|
||||||
|
{ typedef int16_t Type; };
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct StdintTypeForSizeAndSignedness<2, false>
|
||||||
|
{ typedef uint16_t Type; };
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct StdintTypeForSizeAndSignedness<4, true>
|
||||||
|
{ typedef int32_t Type; };
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct StdintTypeForSizeAndSignedness<4, false>
|
||||||
|
{ typedef uint32_t Type; };
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct StdintTypeForSizeAndSignedness<8, true>
|
||||||
|
{ typedef int64_t Type; };
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct StdintTypeForSizeAndSignedness<8, false>
|
||||||
|
{ typedef uint64_t Type; };
|
||||||
|
|
||||||
|
template<typename IntegerType>
|
||||||
|
struct UnsignedType
|
||||||
|
{
|
||||||
|
typedef typename StdintTypeForSizeAndSignedness<sizeof(IntegerType),
|
||||||
|
false>::Type Type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename IntegerType>
|
||||||
|
struct IsSigned
|
||||||
|
{
|
||||||
|
static const bool value = IntegerType(-1) <= IntegerType(0);
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename IntegerType, size_t Size = sizeof(IntegerType)>
|
||||||
|
struct TwiceBiggerType
|
||||||
|
{
|
||||||
|
typedef typename StdintTypeForSizeAndSignedness<
|
||||||
|
sizeof(IntegerType) * 2,
|
||||||
|
IsSigned<IntegerType>::value
|
||||||
|
>::Type Type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename IntegerType>
|
||||||
|
struct TwiceBiggerType<IntegerType, 8>
|
||||||
|
{
|
||||||
|
typedef UnsupportedType Type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename IntegerType>
|
||||||
|
struct PositionOfSignBit
|
||||||
|
{
|
||||||
|
static const size_t value = CHAR_BIT * sizeof(IntegerType) - 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename IntegerType>
|
||||||
|
struct MinValue
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
typedef typename UnsignedType<IntegerType>::Type UnsignedIntegerType;
|
||||||
|
static const size_t PosOfSignBit = PositionOfSignBit<IntegerType>::value;
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Bitwise ops may return a larger type, that's why we cast explicitly.
|
||||||
|
// In C++, left bit shifts on signed values is undefined by the standard
|
||||||
|
// unless the shifted value is representable.
|
||||||
|
// Notice that signed-to-unsigned conversions are always well-defined in
|
||||||
|
// the standard as the value congruent to 2**n, as expected. By contrast,
|
||||||
|
// unsigned-to-signed is only well-defined if the value is representable.
|
||||||
|
static const IntegerType value =
|
||||||
|
IsSigned<IntegerType>::value
|
||||||
|
? IntegerType(UnsignedIntegerType(1) << PosOfSignBit)
|
||||||
|
: IntegerType(0);
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename IntegerType>
|
||||||
|
struct MaxValue
|
||||||
|
{
|
||||||
|
// Tricksy, but covered by the unit test.
|
||||||
|
// Relies heavily on the type of MinValue<IntegerType>::value
|
||||||
|
// being IntegerType.
|
||||||
|
static const IntegerType value = ~MinValue<IntegerType>::value;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Step 3: Implement the actual validity checks.
|
||||||
|
*
|
||||||
|
* Ideas taken from IntegerLib, code different.
|
||||||
|
*/
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline bool
|
||||||
|
HasSignBit(T x)
|
||||||
|
{
|
||||||
|
// In C++, right bit shifts on negative values is undefined by the standard.
|
||||||
|
// Notice that signed-to-unsigned conversions are always well-defined in the
|
||||||
|
// standard, as the value congruent modulo 2**n as expected. By contrast,
|
||||||
|
// unsigned-to-signed is only well-defined if the value is representable.
|
||||||
|
return bool(typename UnsignedType<T>::Type(x)
|
||||||
|
>> PositionOfSignBit<T>::value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bitwise ops may return a larger type, so it's good to use this inline
|
||||||
|
// helper guaranteeing that the result is really of type T.
|
||||||
|
template<typename T>
|
||||||
|
inline T
|
||||||
|
BinaryComplement(T x)
|
||||||
|
{
|
||||||
|
return ~x;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T,
|
||||||
|
typename U,
|
||||||
|
bool IsTSigned = IsSigned<T>::value,
|
||||||
|
bool IsUSigned = IsSigned<U>::value>
|
||||||
|
struct DoesRangeContainRange
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T, typename U, bool Signedness>
|
||||||
|
struct DoesRangeContainRange<T, U, Signedness, Signedness>
|
||||||
|
{
|
||||||
|
static const bool value = sizeof(T) >= sizeof(U);
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T, typename U>
|
||||||
|
struct DoesRangeContainRange<T, U, true, false>
|
||||||
|
{
|
||||||
|
static const bool value = sizeof(T) > sizeof(U);
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T, typename U>
|
||||||
|
struct DoesRangeContainRange<T, U, false, true>
|
||||||
|
{
|
||||||
|
static const bool value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T,
|
||||||
|
typename U,
|
||||||
|
bool IsTSigned = IsSigned<T>::value,
|
||||||
|
bool IsUSigned = IsSigned<U>::value,
|
||||||
|
bool DoesTRangeContainURange = DoesRangeContainRange<T, U>::value>
|
||||||
|
struct IsInRangeImpl {};
|
||||||
|
|
||||||
|
template<typename T, typename U, bool IsTSigned, bool IsUSigned>
|
||||||
|
struct IsInRangeImpl<T, U, IsTSigned, IsUSigned, true>
|
||||||
|
{
|
||||||
|
static bool run(U)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T, typename U>
|
||||||
|
struct IsInRangeImpl<T, U, true, true, false>
|
||||||
|
{
|
||||||
|
static bool run(U x)
|
||||||
|
{
|
||||||
|
return x <= MaxValue<T>::value && x >= MinValue<T>::value;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T, typename U>
|
||||||
|
struct IsInRangeImpl<T, U, false, false, false>
|
||||||
|
{
|
||||||
|
static bool run(U x)
|
||||||
|
{
|
||||||
|
return x <= MaxValue<T>::value;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T, typename U>
|
||||||
|
struct IsInRangeImpl<T, U, true, false, false>
|
||||||
|
{
|
||||||
|
static bool run(U x)
|
||||||
|
{
|
||||||
|
return sizeof(T) > sizeof(U) || x <= U(MaxValue<T>::value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T, typename U>
|
||||||
|
struct IsInRangeImpl<T, U, false, true, false>
|
||||||
|
{
|
||||||
|
static bool run(U x)
|
||||||
|
{
|
||||||
|
return sizeof(T) >= sizeof(U)
|
||||||
|
? x >= 0
|
||||||
|
: x >= 0 && x <= U(MaxValue<T>::value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T, typename U>
|
||||||
|
inline bool
|
||||||
|
IsInRange(U x)
|
||||||
|
{
|
||||||
|
return IsInRangeImpl<T, U>::run(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline bool
|
||||||
|
IsAddValid(T x, T y)
|
||||||
|
{
|
||||||
|
// Addition is valid if the sign of x+y is equal to either that of x or that
|
||||||
|
// of y. Since the value of x+y is undefined if we have a signed type, we
|
||||||
|
// compute it using the unsigned type of the same size.
|
||||||
|
// Beware! These bitwise operations can return a larger integer type,
|
||||||
|
// if T was a small type like int8_t, so we explicitly cast to T.
|
||||||
|
|
||||||
|
typename UnsignedType<T>::Type ux = x;
|
||||||
|
typename UnsignedType<T>::Type uy = y;
|
||||||
|
typename UnsignedType<T>::Type result = ux + uy;
|
||||||
|
return IsSigned<T>::value
|
||||||
|
? HasSignBit(BinaryComplement(T((result ^ x) & (result ^ y))))
|
||||||
|
: BinaryComplement(x) >= y;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline bool
|
||||||
|
IsSubValid(T x, T y)
|
||||||
|
{
|
||||||
|
// Subtraction is valid if either x and y have same sign, or x-y and x have
|
||||||
|
// same sign. Since the value of x-y is undefined if we have a signed type,
|
||||||
|
// we compute it using the unsigned type of the same size.
|
||||||
|
typename UnsignedType<T>::Type ux = x;
|
||||||
|
typename UnsignedType<T>::Type uy = y;
|
||||||
|
typename UnsignedType<T>::Type result = ux - uy;
|
||||||
|
|
||||||
|
return IsSigned<T>::value
|
||||||
|
? HasSignBit(BinaryComplement(T((result ^ x) & (x ^ y))))
|
||||||
|
: x >= y;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T,
|
||||||
|
bool IsSigned = IsSigned<T>::value,
|
||||||
|
bool TwiceBiggerTypeIsSupported =
|
||||||
|
IsSupported<typename TwiceBiggerType<T>::Type>::value>
|
||||||
|
struct IsMulValidImpl {};
|
||||||
|
|
||||||
|
template<typename T, bool IsSigned>
|
||||||
|
struct IsMulValidImpl<T, IsSigned, true>
|
||||||
|
{
|
||||||
|
static bool run(T x, T y)
|
||||||
|
{
|
||||||
|
typedef typename TwiceBiggerType<T>::Type TwiceBiggerType;
|
||||||
|
TwiceBiggerType product = TwiceBiggerType(x) * TwiceBiggerType(y);
|
||||||
|
return IsInRange<T>(product);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct IsMulValidImpl<T, true, false>
|
||||||
|
{
|
||||||
|
static bool run(T x, T y)
|
||||||
|
{
|
||||||
|
const T max = MaxValue<T>::value;
|
||||||
|
const T min = MinValue<T>::value;
|
||||||
|
|
||||||
|
if (x == 0 || y == 0)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (x > 0) {
|
||||||
|
return y > 0
|
||||||
|
? x <= max / y
|
||||||
|
: y >= min / x;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we reach this point, we know that x < 0.
|
||||||
|
return y > 0
|
||||||
|
? x >= min / y
|
||||||
|
: y >= max / x;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct IsMulValidImpl<T, false, false>
|
||||||
|
{
|
||||||
|
static bool run(T x, T y)
|
||||||
|
{
|
||||||
|
return y == 0 || x <= MaxValue<T>::value / y;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline bool
|
||||||
|
IsMulValid(T x, T y)
|
||||||
|
{
|
||||||
|
return IsMulValidImpl<T>::run(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline bool
|
||||||
|
IsDivValid(T x, T y)
|
||||||
|
{
|
||||||
|
// Keep in mind that in the signed case, min/-1 is invalid because abs(min)>max.
|
||||||
|
return y != 0 &&
|
||||||
|
!(IsSigned<T>::value && x == MinValue<T>::value && y == T(-1));
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is just to shut up msvc warnings about negating unsigned ints.
|
||||||
|
template<typename T, bool IsSigned = IsSigned<T>::value>
|
||||||
|
struct OppositeIfSignedImpl
|
||||||
|
{
|
||||||
|
static T run(T x) { return -x; }
|
||||||
|
};
|
||||||
|
template<typename T>
|
||||||
|
struct OppositeIfSignedImpl<T, false>
|
||||||
|
{
|
||||||
|
static T run(T x) { return x; }
|
||||||
|
};
|
||||||
|
template<typename T>
|
||||||
|
inline T
|
||||||
|
OppositeIfSigned(T x)
|
||||||
|
{
|
||||||
|
return OppositeIfSignedImpl<T>::run(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Step 4: Now define the CheckedInt class.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @class CheckedInt
|
||||||
|
* @brief Integer wrapper class checking for integer overflow and other errors
|
||||||
|
* @param T the integer type to wrap. Can be any type among the following:
|
||||||
|
* - any basic integer type such as |int|
|
||||||
|
* - any stdint type such as |int8_t|
|
||||||
|
*
|
||||||
|
* This class implements guarded integer arithmetic. Do a computation, check
|
||||||
|
* that isValid() returns true, you then have a guarantee that no problem, such
|
||||||
|
* as integer overflow, happened during this computation, and you can call
|
||||||
|
* value() to get the plain integer value.
|
||||||
|
*
|
||||||
|
* The arithmetic operators in this class are guaranteed not to raise a signal
|
||||||
|
* (e.g. in case of a division by zero).
|
||||||
|
*
|
||||||
|
* For example, suppose that you want to implement a function that computes
|
||||||
|
* (x+y)/z, that doesn't crash if z==0, and that reports on error (divide by
|
||||||
|
* zero or integer overflow). You could code it as follows:
|
||||||
|
@code
|
||||||
|
bool computeXPlusYOverZ(int x, int y, int z, int *result)
|
||||||
|
{
|
||||||
|
CheckedInt<int> checkedResult = (CheckedInt<int>(x) + y) / z;
|
||||||
|
if (checkedResult.isValid()) {
|
||||||
|
*result = checkedResult.value();
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@endcode
|
||||||
|
*
|
||||||
|
* Implicit conversion from plain integers to checked integers is allowed. The
|
||||||
|
* plain integer is checked to be in range before being casted to the
|
||||||
|
* destination type. This means that the following lines all compile, and the
|
||||||
|
* resulting CheckedInts are correctly detected as valid or invalid:
|
||||||
|
* @code
|
||||||
|
// 1 is of type int, is found to be in range for uint8_t, x is valid
|
||||||
|
CheckedInt<uint8_t> x(1);
|
||||||
|
// -1 is of type int, is found not to be in range for uint8_t, x is invalid
|
||||||
|
CheckedInt<uint8_t> x(-1);
|
||||||
|
// -1 is of type int, is found to be in range for int8_t, x is valid
|
||||||
|
CheckedInt<int8_t> x(-1);
|
||||||
|
// 1000 is of type int16_t, is found not to be in range for int8_t,
|
||||||
|
// x is invalid
|
||||||
|
CheckedInt<int8_t> x(int16_t(1000));
|
||||||
|
// 3123456789 is of type uint32_t, is found not to be in range for int32_t,
|
||||||
|
// x is invalid
|
||||||
|
CheckedInt<int32_t> x(uint32_t(3123456789));
|
||||||
|
* @endcode
|
||||||
|
* Implicit conversion from
|
||||||
|
* checked integers to plain integers is not allowed. As shown in the
|
||||||
|
* above example, to get the value of a checked integer as a normal integer,
|
||||||
|
* call value().
|
||||||
|
*
|
||||||
|
* Arithmetic operations between checked and plain integers is allowed; the
|
||||||
|
* result type is the type of the checked integer.
|
||||||
|
*
|
||||||
|
* Checked integers of different types cannot be used in the same arithmetic
|
||||||
|
* expression.
|
||||||
|
*
|
||||||
|
* There are convenience typedefs for all stdint types, of the following form
|
||||||
|
* (these are just 2 examples):
|
||||||
|
@code
|
||||||
|
typedef CheckedInt<int32_t> CheckedInt32;
|
||||||
|
typedef CheckedInt<uint16_t> CheckedUint16;
|
||||||
|
@endcode
|
||||||
|
*/
|
||||||
|
template<typename T>
|
||||||
|
class CheckedInt
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
T mValue;
|
||||||
|
bool mIsValid;
|
||||||
|
|
||||||
|
template<typename U>
|
||||||
|
CheckedInt(U value, bool isValid) : mValue(value), mIsValid(isValid)
|
||||||
|
{
|
||||||
|
MOZ_STATIC_ASSERT(detail::IsSupported<T>::value,
|
||||||
|
"This type is not supported by CheckedInt");
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Constructs a checked integer with given @a value. The checked integer is
|
||||||
|
* initialized as valid or invalid depending on whether the @a value
|
||||||
|
* is in range.
|
||||||
|
*
|
||||||
|
* This constructor is not explicit. Instead, the type of its argument is a
|
||||||
|
* separate template parameter, ensuring that no conversion is performed
|
||||||
|
* before this constructor is actually called. As explained in the above
|
||||||
|
* documentation for class CheckedInt, this constructor checks that its
|
||||||
|
* argument is valid.
|
||||||
|
*/
|
||||||
|
template<typename U>
|
||||||
|
CheckedInt(U value)
|
||||||
|
: mValue(T(value)),
|
||||||
|
mIsValid(detail::IsInRange<T>(value))
|
||||||
|
{
|
||||||
|
MOZ_STATIC_ASSERT(detail::IsSupported<T>::value,
|
||||||
|
"This type is not supported by CheckedInt");
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Constructs a valid checked integer with initial value 0 */
|
||||||
|
CheckedInt() : mValue(0), mIsValid(true)
|
||||||
|
{
|
||||||
|
MOZ_STATIC_ASSERT(detail::IsSupported<T>::value,
|
||||||
|
"This type is not supported by CheckedInt");
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @returns the actual value */
|
||||||
|
T value() const
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(mIsValid, "Invalid checked integer (division by zero or integer overflow)");
|
||||||
|
return mValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns true if the checked integer is valid, i.e. is not the result
|
||||||
|
* of an invalid operation or of an operation involving an invalid checked
|
||||||
|
* integer
|
||||||
|
*/
|
||||||
|
bool isValid() const
|
||||||
|
{
|
||||||
|
return mIsValid;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename U>
|
||||||
|
friend CheckedInt<U> operator +(const CheckedInt<U>& lhs,
|
||||||
|
const CheckedInt<U>& rhs);
|
||||||
|
template<typename U>
|
||||||
|
CheckedInt& operator +=(U rhs);
|
||||||
|
template<typename U>
|
||||||
|
friend CheckedInt<U> operator -(const CheckedInt<U>& lhs,
|
||||||
|
const CheckedInt<U> &rhs);
|
||||||
|
template<typename U>
|
||||||
|
CheckedInt& operator -=(U rhs);
|
||||||
|
template<typename U>
|
||||||
|
friend CheckedInt<U> operator *(const CheckedInt<U>& lhs,
|
||||||
|
const CheckedInt<U> &rhs);
|
||||||
|
template<typename U>
|
||||||
|
CheckedInt& operator *=(U rhs);
|
||||||
|
template<typename U>
|
||||||
|
friend CheckedInt<U> operator /(const CheckedInt<U>& lhs,
|
||||||
|
const CheckedInt<U> &rhs);
|
||||||
|
template<typename U>
|
||||||
|
CheckedInt& operator /=(U rhs);
|
||||||
|
|
||||||
|
CheckedInt operator -() const
|
||||||
|
{
|
||||||
|
// Circumvent msvc warning about - applied to unsigned int.
|
||||||
|
// if we're unsigned, the only valid case anyway is 0
|
||||||
|
// in which case - is a no-op.
|
||||||
|
T result = detail::OppositeIfSigned(mValue);
|
||||||
|
/* Help the compiler perform RVO (return value optimization). */
|
||||||
|
return CheckedInt(result,
|
||||||
|
mIsValid && detail::IsSubValid(T(0),
|
||||||
|
mValue));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns true if the left and right hand sides are valid
|
||||||
|
* and have the same value.
|
||||||
|
*
|
||||||
|
* Note that these semantics are the reason why we don't offer
|
||||||
|
* a operator!=. Indeed, we'd want to have a!=b be equivalent to !(a==b)
|
||||||
|
* but that would mean that whenever a or b is invalid, a!=b
|
||||||
|
* is always true, which would be very confusing.
|
||||||
|
*
|
||||||
|
* For similar reasons, operators <, >, <=, >= would be very tricky to
|
||||||
|
* specify, so we just avoid offering them.
|
||||||
|
*
|
||||||
|
* Notice that these == semantics are made more reasonable by these facts:
|
||||||
|
* 1. a==b implies equality at the raw data level
|
||||||
|
* (the converse is false, as a==b is never true among invalids)
|
||||||
|
* 2. This is similar to the behavior of IEEE floats, where a==b
|
||||||
|
* means that a and b have the same value *and* neither is NaN.
|
||||||
|
*/
|
||||||
|
bool operator ==(const CheckedInt& other) const
|
||||||
|
{
|
||||||
|
return mIsValid && other.mIsValid && mValue == other.mValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** prefix ++ */
|
||||||
|
CheckedInt& operator++()
|
||||||
|
{
|
||||||
|
*this += 1;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** postfix ++ */
|
||||||
|
CheckedInt operator++(int)
|
||||||
|
{
|
||||||
|
CheckedInt tmp = *this;
|
||||||
|
*this += 1;
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** prefix -- */
|
||||||
|
CheckedInt& operator--()
|
||||||
|
{
|
||||||
|
*this -= 1;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** postfix -- */
|
||||||
|
CheckedInt operator--(int)
|
||||||
|
{
|
||||||
|
CheckedInt tmp = *this;
|
||||||
|
*this -= 1;
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* The !=, <, <=, >, >= operators are disabled:
|
||||||
|
* see the comment on operator==.
|
||||||
|
*/
|
||||||
|
template<typename U>
|
||||||
|
bool operator !=(U other) const MOZ_DELETE;
|
||||||
|
template<typename U>
|
||||||
|
bool operator <(U other) const MOZ_DELETE;
|
||||||
|
template<typename U>
|
||||||
|
bool operator <=(U other) const MOZ_DELETE;
|
||||||
|
template<typename U>
|
||||||
|
bool operator >(U other) const MOZ_DELETE;
|
||||||
|
template<typename U>
|
||||||
|
bool operator >=(U other) const MOZ_DELETE;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define MOZ_CHECKEDINT_BASIC_BINARY_OPERATOR(NAME, OP) \
|
||||||
|
template<typename T> \
|
||||||
|
inline CheckedInt<T> operator OP(const CheckedInt<T> &lhs, \
|
||||||
|
const CheckedInt<T> &rhs) \
|
||||||
|
{ \
|
||||||
|
if (!detail::Is##NAME##Valid(lhs.mValue, rhs.mValue)) \
|
||||||
|
return CheckedInt<T>(0, false); \
|
||||||
|
\
|
||||||
|
return CheckedInt<T>(lhs.mValue OP rhs.mValue, \
|
||||||
|
lhs.mIsValid && rhs.mIsValid); \
|
||||||
|
}
|
||||||
|
|
||||||
|
MOZ_CHECKEDINT_BASIC_BINARY_OPERATOR(Add, +)
|
||||||
|
MOZ_CHECKEDINT_BASIC_BINARY_OPERATOR(Sub, -)
|
||||||
|
MOZ_CHECKEDINT_BASIC_BINARY_OPERATOR(Mul, *)
|
||||||
|
MOZ_CHECKEDINT_BASIC_BINARY_OPERATOR(Div, /)
|
||||||
|
|
||||||
|
#undef MOZ_CHECKEDINT_BASIC_BINARY_OPERATOR
|
||||||
|
|
||||||
|
// Implement castToCheckedInt<T>(x), making sure that
|
||||||
|
// - it allows x to be either a CheckedInt<T> or any integer type
|
||||||
|
// that can be casted to T
|
||||||
|
// - if x is already a CheckedInt<T>, we just return a reference to it,
|
||||||
|
// instead of copying it (optimization)
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
template<typename T, typename U>
|
||||||
|
struct CastToCheckedIntImpl
|
||||||
|
{
|
||||||
|
typedef CheckedInt<T> ReturnType;
|
||||||
|
static CheckedInt<T> run(U u) { return u; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct CastToCheckedIntImpl<T, CheckedInt<T> >
|
||||||
|
{
|
||||||
|
typedef const CheckedInt<T>& ReturnType;
|
||||||
|
static const CheckedInt<T>& run(const CheckedInt<T>& u) { return u; }
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
template<typename T, typename U>
|
||||||
|
inline typename detail::CastToCheckedIntImpl<T, U>::ReturnType
|
||||||
|
castToCheckedInt(U u)
|
||||||
|
{
|
||||||
|
return detail::CastToCheckedIntImpl<T, U>::run(u);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MOZ_CHECKEDINT_CONVENIENCE_BINARY_OPERATORS(OP, COMPOUND_OP) \
|
||||||
|
template<typename T> \
|
||||||
|
template<typename U> \
|
||||||
|
CheckedInt<T>& CheckedInt<T>::operator COMPOUND_OP(U rhs) \
|
||||||
|
{ \
|
||||||
|
*this = *this OP castToCheckedInt<T>(rhs); \
|
||||||
|
return *this; \
|
||||||
|
} \
|
||||||
|
template<typename T, typename U> \
|
||||||
|
inline CheckedInt<T> operator OP(const CheckedInt<T> &lhs, U rhs) \
|
||||||
|
{ \
|
||||||
|
return lhs OP castToCheckedInt<T>(rhs); \
|
||||||
|
} \
|
||||||
|
template<typename T, typename U> \
|
||||||
|
inline CheckedInt<T> operator OP(U lhs, const CheckedInt<T> &rhs) \
|
||||||
|
{ \
|
||||||
|
return castToCheckedInt<T>(lhs) OP rhs; \
|
||||||
|
}
|
||||||
|
|
||||||
|
MOZ_CHECKEDINT_CONVENIENCE_BINARY_OPERATORS(+, +=)
|
||||||
|
MOZ_CHECKEDINT_CONVENIENCE_BINARY_OPERATORS(*, *=)
|
||||||
|
MOZ_CHECKEDINT_CONVENIENCE_BINARY_OPERATORS(-, -=)
|
||||||
|
MOZ_CHECKEDINT_CONVENIENCE_BINARY_OPERATORS(/, /=)
|
||||||
|
|
||||||
|
#undef MOZ_CHECKEDINT_CONVENIENCE_BINARY_OPERATORS
|
||||||
|
|
||||||
|
template<typename T, typename U>
|
||||||
|
inline bool
|
||||||
|
operator ==(const CheckedInt<T> &lhs, U rhs)
|
||||||
|
{
|
||||||
|
return lhs == castToCheckedInt<T>(rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, typename U>
|
||||||
|
inline bool
|
||||||
|
operator ==(U lhs, const CheckedInt<T> &rhs)
|
||||||
|
{
|
||||||
|
return castToCheckedInt<T>(lhs) == rhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convenience typedefs.
|
||||||
|
typedef CheckedInt<int8_t> CheckedInt8;
|
||||||
|
typedef CheckedInt<uint8_t> CheckedUint8;
|
||||||
|
typedef CheckedInt<int16_t> CheckedInt16;
|
||||||
|
typedef CheckedInt<uint16_t> CheckedUint16;
|
||||||
|
typedef CheckedInt<int32_t> CheckedInt32;
|
||||||
|
typedef CheckedInt<uint32_t> CheckedUint32;
|
||||||
|
typedef CheckedInt<int64_t> CheckedInt64;
|
||||||
|
typedef CheckedInt<uint64_t> CheckedUint64;
|
||||||
|
|
||||||
|
} // namespace mozilla
|
||||||
|
|
||||||
|
#endif /* mozilla_CheckedInt_h_ */
|
|
@ -226,16 +226,6 @@ MOZ_DOUBLE_MIN_VALUE()
|
||||||
return pun.d;
|
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
|
static MOZ_ALWAYS_INLINE int
|
||||||
MOZ_DOUBLE_IS_INT32(double d, int32_t* i)
|
MOZ_DOUBLE_IS_INT32(double d, int32_t* i)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,42 +1,7 @@
|
||||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
/* -*- 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
|
||||||
/* ***** BEGIN LICENSE BLOCK *****
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
*
|
|
||||||
* 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. */
|
/* Implementation of macros to ensure correct use of RAII Auto* objects. */
|
||||||
|
|
||||||
|
@ -52,6 +17,7 @@
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The following classes are designed to cause assertions to detect
|
* The following classes are designed to cause assertions to detect
|
||||||
* inadvertent use of guard objects as temporaries. In other words,
|
* inadvertent use of guard objects as temporaries. In other words,
|
||||||
|
@ -59,11 +25,11 @@ namespace detail {
|
||||||
* destructor (and is never otherwise referenced), the intended use
|
* destructor (and is never otherwise referenced), the intended use
|
||||||
* might be:
|
* might be:
|
||||||
*
|
*
|
||||||
* AutoRestore savePainting(mIsPainting);
|
* AutoRestore savePainting(mIsPainting);
|
||||||
*
|
*
|
||||||
* but is is easy to accidentally write:
|
* but is is easy to accidentally write:
|
||||||
*
|
*
|
||||||
* AutoRestore(mIsPainting);
|
* AutoRestore(mIsPainting);
|
||||||
*
|
*
|
||||||
* which compiles just fine, but runs the destructor well before the
|
* which compiles just fine, but runs the destructor well before the
|
||||||
* intended time.
|
* intended time.
|
||||||
|
@ -106,14 +72,14 @@ class MOZ_EXPORT_API(GuardObjectNotifier)
|
||||||
bool* statementDone;
|
bool* statementDone;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
GuardObjectNotifier() : statementDone(NULL) {}
|
GuardObjectNotifier() : statementDone(NULL) { }
|
||||||
|
|
||||||
~GuardObjectNotifier() {
|
~GuardObjectNotifier() {
|
||||||
*statementDone = true;
|
*statementDone = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setStatementDone(bool* statementIsDone) {
|
void setStatementDone(bool* statementIsDone) {
|
||||||
statementDone = statementIsDone;
|
statementDone = statementIsDone;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -123,25 +89,24 @@ class MOZ_EXPORT_API(GuardObjectNotificationReceiver)
|
||||||
bool statementDone;
|
bool statementDone;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
GuardObjectNotificationReceiver() : statementDone(false) {}
|
GuardObjectNotificationReceiver() : statementDone(false) { }
|
||||||
|
|
||||||
~GuardObjectNotificationReceiver() {
|
~GuardObjectNotificationReceiver() {
|
||||||
/*
|
/*
|
||||||
* Assert that the guard object was not used as a temporary.
|
* Assert that the guard object was not used as a temporary. (Note that
|
||||||
* (Note that this assert might also fire if init is not called
|
* this assert might also fire if init is not called because the guard
|
||||||
* because the guard object's implementation is not using the
|
* object's implementation is not using the above macros correctly.)
|
||||||
* above macros correctly.)
|
*/
|
||||||
*/
|
MOZ_ASSERT(statementDone);
|
||||||
MOZ_ASSERT(statementDone);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void init(const GuardObjectNotifier& constNotifier) {
|
void init(const GuardObjectNotifier& constNotifier) {
|
||||||
/*
|
/*
|
||||||
* constNotifier is passed as a const reference so that we can pass a
|
* constNotifier is passed as a const reference so that we can pass a
|
||||||
* temporary, but we really intend it as non-const.
|
* temporary, but we really intend it as non-const.
|
||||||
*/
|
*/
|
||||||
GuardObjectNotifier& notifier = const_cast<GuardObjectNotifier&>(constNotifier);
|
GuardObjectNotifier& notifier = const_cast<GuardObjectNotifier&>(constNotifier);
|
||||||
notifier.setStatementDone(&statementDone);
|
notifier.setStatementDone(&statementDone);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
/* -*- 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
|
||||||
*
|
|
||||||
* 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,
|
* 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/. */
|
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
/* Utilities for hashing */
|
/* Utilities for hashing. */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This file exports functions for hashing data down to a 32-bit value,
|
* This file exports functions for hashing data down to a 32-bit value,
|
||||||
|
@ -26,16 +24,18 @@
|
||||||
*
|
*
|
||||||
* You can chain these functions together to hash complex objects. For example:
|
* You can chain these functions together to hash complex objects. For example:
|
||||||
*
|
*
|
||||||
* class ComplexObject {
|
* class ComplexObject
|
||||||
* char* str;
|
* {
|
||||||
* uint32_t uint1, uint2;
|
* char* str;
|
||||||
* void (*callbackFn)();
|
* uint32_t uint1, uint2;
|
||||||
|
* void (*callbackFn)();
|
||||||
*
|
*
|
||||||
* uint32_t Hash() {
|
* public:
|
||||||
* uint32_t hash = HashString(str);
|
* uint32_t hash() {
|
||||||
* hash = AddToHash(hash, uint1, uint2);
|
* uint32_t hash = HashString(str);
|
||||||
* return AddToHash(hash, callbackFn);
|
* hash = AddToHash(hash, uint1, uint2);
|
||||||
* }
|
* return AddToHash(hash, callbackFn);
|
||||||
|
* }
|
||||||
* };
|
* };
|
||||||
*
|
*
|
||||||
* If you want to hash an nsAString or nsACString, use the HashString functions
|
* If you want to hash an nsAString or nsACString, use the HashString functions
|
||||||
|
@ -48,6 +48,7 @@
|
||||||
#include "mozilla/Assertions.h"
|
#include "mozilla/Assertions.h"
|
||||||
#include "mozilla/Attributes.h"
|
#include "mozilla/Attributes.h"
|
||||||
#include "mozilla/StandardInteger.h"
|
#include "mozilla/StandardInteger.h"
|
||||||
|
#include "mozilla/Types.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* -*- 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
|
/* 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,
|
* 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/. */
|
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
@ -7,8 +8,8 @@
|
||||||
* boolean predicate should be branch-predicted.
|
* boolean predicate should be branch-predicted.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef Likely_h_
|
#ifndef mozilla_Likely_h_
|
||||||
#define Likely_h_
|
#define mozilla_Likely_h_
|
||||||
|
|
||||||
#if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 2))
|
#if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 2))
|
||||||
# define MOZ_LIKELY(x) (__builtin_expect((x), 1))
|
# define MOZ_LIKELY(x) (__builtin_expect((x), 1))
|
||||||
|
@ -18,4 +19,4 @@
|
||||||
# define MOZ_UNLIKELY(x) (x)
|
# define MOZ_UNLIKELY(x) (x)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* Likely_h_ */
|
#endif /* mozilla_Likely_h_ */
|
||||||
|
|
|
@ -1,42 +1,7 @@
|
||||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
* vim: set ts=4 sw=4 tw=80 et cin:
|
/* 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
|
||||||
* ***** BEGIN LICENSE BLOCK *****
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
* 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. */
|
/* A type-safe doubly-linked list class. */
|
||||||
|
|
||||||
|
@ -53,36 +18,30 @@
|
||||||
*
|
*
|
||||||
* class Observer : public LinkedListElement<Observer>
|
* class Observer : public LinkedListElement<Observer>
|
||||||
* {
|
* {
|
||||||
* void observe(char* topic) { ... }
|
* public:
|
||||||
|
* void observe(char* topic) { ... }
|
||||||
* };
|
* };
|
||||||
*
|
*
|
||||||
* class ObserverContainer
|
* class ObserverContainer
|
||||||
* {
|
* {
|
||||||
* private:
|
* private:
|
||||||
* LinkedList<ElemType> list;
|
* LinkedList<Observer> list;
|
||||||
*
|
*
|
||||||
* public:
|
* public:
|
||||||
*
|
* void addObserver(Observer* observer) {
|
||||||
* void addObserver(Observer* observer)
|
* // Will assert if |observer| is part of another list.
|
||||||
* {
|
* list.insertBack(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.
|
||||||
* void removeObserver(Observer* observer)
|
* observer.remove();
|
||||||
* {
|
* }
|
||||||
* // 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);
|
||||||
* void notifyObservers(char* topic)
|
|
||||||
* {
|
|
||||||
* for (Observer* o = list.getFirst();
|
|
||||||
* o != NULL;
|
|
||||||
* o = o->getNext()) {
|
|
||||||
* o->Observe(topic);
|
|
||||||
* }
|
* }
|
||||||
* }
|
|
||||||
* };
|
* };
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
@ -137,43 +96,41 @@ class LinkedListElement
|
||||||
* lists, and supporting this painlessly was a key design criterion.
|
* lists, and supporting this painlessly was a key design criterion.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
private:
|
private:
|
||||||
LinkedListElement* next;
|
LinkedListElement* next;
|
||||||
LinkedListElement* prev;
|
LinkedListElement* prev;
|
||||||
const bool isSentinel;
|
const bool isSentinel;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
LinkedListElement()
|
LinkedListElement() : next(this), prev(this), isSentinel(false) { }
|
||||||
: next(this)
|
|
||||||
, prev(this)
|
|
||||||
, isSentinel(false)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get the next element in the list, or NULL if this is the last element in
|
* Get the next element in the list, or NULL if this is the last element in
|
||||||
* the list.
|
* the list.
|
||||||
*/
|
*/
|
||||||
T* getNext()
|
T* getNext() {
|
||||||
{
|
return next->asT();
|
||||||
return next->asT();
|
}
|
||||||
|
const T* getNext() const {
|
||||||
|
return next->asT();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get the previous element in the list, or NULL if this is the first element
|
* Get the previous element in the list, or NULL if this is the first element
|
||||||
* in the list.
|
* in the list.
|
||||||
*/
|
*/
|
||||||
T* getPrevious()
|
T* getPrevious() {
|
||||||
{
|
return prev->asT();
|
||||||
return prev->asT();
|
}
|
||||||
|
const T* getPrevious() const {
|
||||||
|
return prev->asT();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Insert elem after this element in the list. |this| must be part of a
|
* 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.
|
* linked list when you call setNext(); otherwise, this method will assert.
|
||||||
*/
|
*/
|
||||||
void setNext(T* elem)
|
void setNext(T* elem) {
|
||||||
{
|
|
||||||
MOZ_ASSERT(isInList());
|
MOZ_ASSERT(isInList());
|
||||||
setNextUnsafe(elem);
|
setNextUnsafe(elem);
|
||||||
}
|
}
|
||||||
|
@ -183,50 +140,44 @@ public:
|
||||||
* linked list when you call setPrevious(); otherwise, this method will
|
* linked list when you call setPrevious(); otherwise, this method will
|
||||||
* assert.
|
* assert.
|
||||||
*/
|
*/
|
||||||
void setPrevious(T* elem)
|
void setPrevious(T* elem) {
|
||||||
{
|
MOZ_ASSERT(isInList());
|
||||||
MOZ_ASSERT(isInList());
|
setPreviousUnsafe(elem);
|
||||||
setPreviousUnsafe(elem);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Remove this element from the list which contains it. If this element is
|
* Remove this element from the list which contains it. If this element is
|
||||||
* not currently part of a linked list, this method asserts.
|
* not currently part of a linked list, this method asserts.
|
||||||
*/
|
*/
|
||||||
void remove()
|
void remove() {
|
||||||
{
|
MOZ_ASSERT(isInList());
|
||||||
MOZ_ASSERT(isInList());
|
|
||||||
|
|
||||||
prev->next = next;
|
prev->next = next;
|
||||||
next->prev = prev;
|
next->prev = prev;
|
||||||
next = this;
|
next = this;
|
||||||
prev = this;
|
prev = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return true if |this| part is of a linked list, and false otherwise.
|
* Return true if |this| part is of a linked list, and false otherwise.
|
||||||
*/
|
*/
|
||||||
bool isInList()
|
bool isInList() const {
|
||||||
{
|
MOZ_ASSERT((next == this) == (prev == this));
|
||||||
MOZ_ASSERT((next == this) == (prev == this));
|
return next != this;
|
||||||
return next != this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
LinkedListElement& operator=(const LinkedList<T>& other) MOZ_DELETE;
|
|
||||||
LinkedListElement(const LinkedList<T>& other) MOZ_DELETE;
|
|
||||||
|
|
||||||
friend class LinkedList<T>;
|
friend class LinkedList<T>;
|
||||||
|
|
||||||
enum NodeKind {
|
enum NodeKind {
|
||||||
NODE_KIND_NORMAL,
|
NODE_KIND_NORMAL,
|
||||||
NODE_KIND_SENTINEL
|
NODE_KIND_SENTINEL
|
||||||
};
|
};
|
||||||
|
|
||||||
LinkedListElement(NodeKind nodeKind)
|
LinkedListElement(NodeKind nodeKind)
|
||||||
: next(this)
|
: next(this),
|
||||||
, prev(this)
|
prev(this),
|
||||||
, isSentinel(nodeKind == NODE_KIND_SENTINEL)
|
isSentinel(nodeKind == NODE_KIND_SENTINEL)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -234,125 +185,123 @@ private:
|
||||||
* Return |this| cast to T* if we're a normal node, or return NULL if we're
|
* Return |this| cast to T* if we're a normal node, or return NULL if we're
|
||||||
* a sentinel node.
|
* a sentinel node.
|
||||||
*/
|
*/
|
||||||
T* asT()
|
T* asT() {
|
||||||
{
|
if (isSentinel)
|
||||||
if (isSentinel)
|
return NULL;
|
||||||
return NULL;
|
|
||||||
|
|
||||||
return static_cast<T*>(this);
|
return static_cast<T*>(this);
|
||||||
|
}
|
||||||
|
const T* asT() const {
|
||||||
|
if (isSentinel)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return static_cast<const T*>(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Insert elem after this element, but don't check that this element is in
|
* Insert elem after this element, but don't check that this element is in
|
||||||
* the list. This is called by LinkedList::insertFront().
|
* the list. This is called by LinkedList::insertFront().
|
||||||
*/
|
*/
|
||||||
void setNextUnsafe(T* elem)
|
void setNextUnsafe(T* elem) {
|
||||||
{
|
LinkedListElement *listElem = static_cast<LinkedListElement*>(elem);
|
||||||
LinkedListElement *listElem = static_cast<LinkedListElement*>(elem);
|
MOZ_ASSERT(!listElem->isInList());
|
||||||
MOZ_ASSERT(!listElem->isInList());
|
|
||||||
|
|
||||||
listElem->next = this->next;
|
listElem->next = this->next;
|
||||||
listElem->prev = this;
|
listElem->prev = this;
|
||||||
this->next->prev = listElem;
|
this->next->prev = listElem;
|
||||||
this->next = listElem;
|
this->next = listElem;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Insert elem before this element, but don't check that this element is in
|
* Insert elem before this element, but don't check that this element is in
|
||||||
* the list. This is called by LinkedList::insertBack().
|
* the list. This is called by LinkedList::insertBack().
|
||||||
*/
|
*/
|
||||||
void setPreviousUnsafe(T* elem)
|
void setPreviousUnsafe(T* elem) {
|
||||||
{
|
LinkedListElement<T>* listElem = static_cast<LinkedListElement<T>*>(elem);
|
||||||
LinkedListElement<T>* listElem = static_cast<LinkedListElement<T>*>(elem);
|
MOZ_ASSERT(!listElem->isInList());
|
||||||
MOZ_ASSERT(!listElem->isInList());
|
|
||||||
|
|
||||||
listElem->next = this;
|
listElem->next = this;
|
||||||
listElem->prev = this->prev;
|
listElem->prev = this->prev;
|
||||||
this->prev->next = listElem;
|
this->prev->next = listElem;
|
||||||
this->prev = listElem;
|
this->prev = listElem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
LinkedListElement& operator=(const LinkedList<T>& other) MOZ_DELETE;
|
||||||
|
LinkedListElement(const LinkedList<T>& other) MOZ_DELETE;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class LinkedList
|
class LinkedList
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
LinkedListElement<T> sentinel;
|
LinkedListElement<T> sentinel;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
LinkedList& operator=(const LinkedList<T>& other) MOZ_DELETE;
|
LinkedList() : sentinel(LinkedListElement<T>::NODE_KIND_SENTINEL) { }
|
||||||
LinkedList(const LinkedList<T>& other) MOZ_DELETE;
|
|
||||||
|
|
||||||
LinkedList()
|
|
||||||
: sentinel(LinkedListElement<T>::NODE_KIND_SENTINEL)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add elem to the front of the list.
|
* Add elem to the front of the list.
|
||||||
*/
|
*/
|
||||||
void insertFront(T* elem)
|
void insertFront(T* elem) {
|
||||||
{
|
/* Bypass setNext()'s this->isInList() assertion. */
|
||||||
/* Bypass setNext()'s this->isInList() assertion. */
|
sentinel.setNextUnsafe(elem);
|
||||||
sentinel.setNextUnsafe(elem);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add elem to the back of the list.
|
* Add elem to the back of the list.
|
||||||
*/
|
*/
|
||||||
void insertBack(T* elem)
|
void insertBack(T* elem) {
|
||||||
{
|
sentinel.setPreviousUnsafe(elem);
|
||||||
sentinel.setPreviousUnsafe(elem);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get the first element of the list, or NULL if the list is empty.
|
* Get the first element of the list, or NULL if the list is empty.
|
||||||
*/
|
*/
|
||||||
T* getFirst()
|
T* getFirst() {
|
||||||
{
|
return sentinel.getNext();
|
||||||
return sentinel.getNext();
|
}
|
||||||
|
const T* getFirst() const {
|
||||||
|
return sentinel.getNext();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get the last element of the list, or NULL if the list is empty.
|
* Get the last element of the list, or NULL if the list is empty.
|
||||||
*/
|
*/
|
||||||
T* getLast()
|
T* getLast() {
|
||||||
{
|
return sentinel.getPrevious();
|
||||||
return sentinel.getPrevious();
|
}
|
||||||
|
const T* getLast() const {
|
||||||
|
return sentinel.getPrevious();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get and remove the first element of the list. If the list is empty,
|
* Get and remove the first element of the list. If the list is empty,
|
||||||
* return NULL.
|
* return NULL.
|
||||||
*/
|
*/
|
||||||
T* popFirst()
|
T* popFirst() {
|
||||||
{
|
T* ret = sentinel.getNext();
|
||||||
T* ret = sentinel.getNext();
|
if (ret)
|
||||||
if (ret)
|
static_cast<LinkedListElement<T>*>(ret)->remove();
|
||||||
static_cast<LinkedListElement<T>*>(ret)->remove();
|
return ret;
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get and remove the last element of the list. If the list is empty,
|
* Get and remove the last element of the list. If the list is empty,
|
||||||
* return NULL.
|
* return NULL.
|
||||||
*/
|
*/
|
||||||
T* popLast()
|
T* popLast() {
|
||||||
{
|
T* ret = sentinel.getPrevious();
|
||||||
T* ret = sentinel.getPrevious();
|
if (ret)
|
||||||
if (ret)
|
static_cast<LinkedListElement<T>*>(ret)->remove();
|
||||||
static_cast<LinkedListElement<T>*>(ret)->remove();
|
return ret;
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return true if the list is empty, or false otherwise.
|
* Return true if the list is empty, or false otherwise.
|
||||||
*/
|
*/
|
||||||
bool isEmpty()
|
bool isEmpty() const {
|
||||||
{
|
return !sentinel.isInList();
|
||||||
return !sentinel.isInList();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -361,71 +310,73 @@ public:
|
||||||
* This runs in time linear to the list's length, because we have to mark
|
* This runs in time linear to the list's length, because we have to mark
|
||||||
* each element as not in the list.
|
* each element as not in the list.
|
||||||
*/
|
*/
|
||||||
void clear()
|
void clear() {
|
||||||
{
|
while (popFirst())
|
||||||
while (popFirst())
|
continue;
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* In a debug build, make sure that the list is sane (no cycles, consistent
|
* 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.
|
* next/prev pointers, only one sentinel). Has no effect in release builds.
|
||||||
*/
|
*/
|
||||||
void debugAssertIsSane()
|
void debugAssertIsSane() const {
|
||||||
{
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
/*
|
const LinkedListElement<T>* slow;
|
||||||
* Check for cycles in the forward singly-linked list using the
|
const LinkedListElement<T>* fast1;
|
||||||
* tortoise/hare algorithm.
|
const LinkedListElement<T>* fast2;
|
||||||
*/
|
|
||||||
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 forward singly-linked list using the
|
||||||
}
|
* tortoise/hare algorithm.
|
||||||
|
*/
|
||||||
|
for (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. */
|
/* Check for cycles in the backward singly-linked list. */
|
||||||
for (LinkedListElement<T>* slow = sentinel.prev,
|
for (slow = sentinel.prev,
|
||||||
* fast1 = sentinel.prev->prev,
|
fast1 = sentinel.prev->prev,
|
||||||
* fast2 = sentinel.prev->prev->prev;
|
fast2 = sentinel.prev->prev->prev;
|
||||||
slow != sentinel && fast1 != sentinel && fast2 != sentinel;
|
slow != sentinel && fast1 != sentinel && fast2 != sentinel;
|
||||||
slow = slow->prev,
|
slow = slow->prev, fast1 = fast2->prev, fast2 = fast1->prev)
|
||||||
fast1 = fast2->prev,
|
{
|
||||||
fast2 = fast1->prev) {
|
MOZ_ASSERT(slow != fast1);
|
||||||
|
MOZ_ASSERT(slow != fast2);
|
||||||
|
}
|
||||||
|
|
||||||
MOZ_ASSERT(slow != fast1);
|
/*
|
||||||
MOZ_ASSERT(slow != fast2);
|
* Check that |sentinel| is the only node in the list with
|
||||||
}
|
* isSentinel == true.
|
||||||
|
*/
|
||||||
|
for (const LinkedListElement<T>* elem = sentinel.next;
|
||||||
|
elem != sentinel;
|
||||||
|
elem = elem->next)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(!elem->isSentinel);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/* Check that the next/prev pointers match up. */
|
||||||
* Check that |sentinel| is the only node in the list with
|
const LinkedListElement<T>* prev = sentinel;
|
||||||
* isSentinel == true.
|
const LinkedListElement<T>* cur = sentinel.next;
|
||||||
*/
|
do {
|
||||||
for (LinkedListElement<T>* elem = sentinel.next;
|
MOZ_ASSERT(cur->prev == prev);
|
||||||
elem != sentinel;
|
MOZ_ASSERT(prev->next == cur);
|
||||||
elem = elem->next) {
|
|
||||||
|
|
||||||
MOZ_ASSERT(!elem->isSentinel);
|
prev = cur;
|
||||||
}
|
cur = cur->next;
|
||||||
|
} while (cur != sentinel);
|
||||||
/* 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 */
|
#endif /* ifdef DEBUG */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
LinkedList& operator=(const LinkedList<T>& other) MOZ_DELETE;
|
||||||
|
LinkedList(const LinkedList<T>& other) MOZ_DELETE;
|
||||||
};
|
};
|
||||||
|
|
||||||
} /* namespace mozilla */
|
} /* namespace mozilla */
|
||||||
|
|
|
@ -1,42 +1,7 @@
|
||||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
/* -*- 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
|
||||||
* ***** BEGIN LICENSE BLOCK *****
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
* 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
|
* Implements a smart pointer asserted to remain within a range specified at
|
||||||
|
@ -71,7 +36,7 @@ namespace mozilla {
|
||||||
* explicitly convert to T*. Keep in mind that the raw pointer of course won't
|
* explicitly convert to T*. Keep in mind that the raw pointer of course won't
|
||||||
* implement bounds checking in debug builds.
|
* implement bounds checking in debug builds.
|
||||||
*/
|
*/
|
||||||
template <typename T>
|
template<typename T>
|
||||||
class RangedPtr
|
class RangedPtr
|
||||||
{
|
{
|
||||||
T* ptr;
|
T* ptr;
|
||||||
|
@ -82,16 +47,16 @@ class RangedPtr
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void checkSanity() {
|
void checkSanity() {
|
||||||
MOZ_ASSERT(rangeStart <= ptr);
|
MOZ_ASSERT(rangeStart <= ptr);
|
||||||
MOZ_ASSERT(ptr <= rangeEnd);
|
MOZ_ASSERT(ptr <= rangeEnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Creates a new pointer for |ptr|, restricted to this pointer's range. */
|
/* Creates a new pointer for |ptr|, restricted to this pointer's range. */
|
||||||
RangedPtr<T> create(T *ptr) const {
|
RangedPtr<T> create(T *ptr) const {
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
return RangedPtr<T>(ptr, rangeStart, rangeEnd);
|
return RangedPtr<T>(ptr, rangeStart, rangeEnd);
|
||||||
#else
|
#else
|
||||||
return RangedPtr<T>(ptr, NULL, size_t(0));
|
return RangedPtr<T>(ptr, NULL, size_t(0));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,8 +67,8 @@ class RangedPtr
|
||||||
, rangeStart(start), rangeEnd(end)
|
, rangeStart(start), rangeEnd(end)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(rangeStart <= rangeEnd);
|
MOZ_ASSERT(rangeStart <= rangeEnd);
|
||||||
checkSanity();
|
checkSanity();
|
||||||
}
|
}
|
||||||
RangedPtr(T* p, T* start, size_t length)
|
RangedPtr(T* p, T* start, size_t length)
|
||||||
: ptr(p)
|
: ptr(p)
|
||||||
|
@ -111,9 +76,9 @@ class RangedPtr
|
||||||
, rangeStart(start), rangeEnd(start + length)
|
, rangeStart(start), rangeEnd(start + length)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(length <= size_t(-1) / sizeof(T));
|
MOZ_ASSERT(length <= size_t(-1) / sizeof(T));
|
||||||
MOZ_ASSERT(uintptr_t(rangeStart) + length * sizeof(T) >= uintptr_t(rangeStart));
|
MOZ_ASSERT(uintptr_t(rangeStart) + length * sizeof(T) >= uintptr_t(rangeStart));
|
||||||
checkSanity();
|
checkSanity();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Equivalent to RangedPtr(p, p, length). */
|
/* Equivalent to RangedPtr(p, p, length). */
|
||||||
|
@ -123,9 +88,9 @@ class RangedPtr
|
||||||
, rangeStart(p), rangeEnd(p + length)
|
, rangeStart(p), rangeEnd(p + length)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(length <= size_t(-1) / sizeof(T));
|
MOZ_ASSERT(length <= size_t(-1) / sizeof(T));
|
||||||
MOZ_ASSERT(uintptr_t(rangeStart) + length * sizeof(T) >= uintptr_t(rangeStart));
|
MOZ_ASSERT(uintptr_t(rangeStart) + length * sizeof(T) >= uintptr_t(rangeStart));
|
||||||
checkSanity();
|
checkSanity();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Equivalent to RangedPtr(arr, arr, N). */
|
/* Equivalent to RangedPtr(arr, arr, N). */
|
||||||
|
@ -140,7 +105,7 @@ class RangedPtr
|
||||||
}
|
}
|
||||||
|
|
||||||
T* get() const {
|
T* get() const {
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -154,23 +119,23 @@ class RangedPtr
|
||||||
* p1 = RangedPtr<char>(arr2, 3); // asserts
|
* p1 = RangedPtr<char>(arr2, 3); // asserts
|
||||||
*/
|
*/
|
||||||
RangedPtr<T>& operator=(const RangedPtr<T>& other) {
|
RangedPtr<T>& operator=(const RangedPtr<T>& other) {
|
||||||
MOZ_ASSERT(rangeStart == other.rangeStart);
|
MOZ_ASSERT(rangeStart == other.rangeStart);
|
||||||
MOZ_ASSERT(rangeEnd == other.rangeEnd);
|
MOZ_ASSERT(rangeEnd == other.rangeEnd);
|
||||||
ptr = other.ptr;
|
ptr = other.ptr;
|
||||||
checkSanity();
|
checkSanity();
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
RangedPtr<T> operator+(size_t inc) {
|
RangedPtr<T> operator+(size_t inc) {
|
||||||
MOZ_ASSERT(inc <= size_t(-1) / sizeof(T));
|
MOZ_ASSERT(inc <= size_t(-1) / sizeof(T));
|
||||||
MOZ_ASSERT(ptr + inc > ptr);
|
MOZ_ASSERT(ptr + inc > ptr);
|
||||||
return create(ptr + inc);
|
return create(ptr + inc);
|
||||||
}
|
}
|
||||||
|
|
||||||
RangedPtr<T> operator-(size_t dec) {
|
RangedPtr<T> operator-(size_t dec) {
|
||||||
MOZ_ASSERT(dec <= size_t(-1) / sizeof(T));
|
MOZ_ASSERT(dec <= size_t(-1) / sizeof(T));
|
||||||
MOZ_ASSERT(ptr - dec < ptr);
|
MOZ_ASSERT(ptr - dec < ptr);
|
||||||
return create(ptr - dec);
|
return create(ptr - dec);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -179,97 +144,97 @@ class RangedPtr
|
||||||
*/
|
*/
|
||||||
template <typename U>
|
template <typename U>
|
||||||
RangedPtr<T>& operator=(U* p) {
|
RangedPtr<T>& operator=(U* p) {
|
||||||
*this = create(p);
|
*this = create(p);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename U>
|
template <typename U>
|
||||||
RangedPtr<T>& operator=(const RangedPtr<U>& p) {
|
RangedPtr<T>& operator=(const RangedPtr<U>& p) {
|
||||||
MOZ_ASSERT(rangeStart <= p.ptr);
|
MOZ_ASSERT(rangeStart <= p.ptr);
|
||||||
MOZ_ASSERT(p.ptr <= rangeEnd);
|
MOZ_ASSERT(p.ptr <= rangeEnd);
|
||||||
ptr = p.ptr;
|
ptr = p.ptr;
|
||||||
checkSanity();
|
checkSanity();
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
RangedPtr<T>& operator++() {
|
RangedPtr<T>& operator++() {
|
||||||
return (*this += 1);
|
return (*this += 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
RangedPtr<T> operator++(int) {
|
RangedPtr<T> operator++(int) {
|
||||||
RangedPtr<T> rcp = *this;
|
RangedPtr<T> rcp = *this;
|
||||||
++*this;
|
++*this;
|
||||||
return rcp;
|
return rcp;
|
||||||
}
|
}
|
||||||
|
|
||||||
RangedPtr<T>& operator--() {
|
RangedPtr<T>& operator--() {
|
||||||
return (*this -= 1);
|
return (*this -= 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
RangedPtr<T> operator--(int) {
|
RangedPtr<T> operator--(int) {
|
||||||
RangedPtr<T> rcp = *this;
|
RangedPtr<T> rcp = *this;
|
||||||
--*this;
|
--*this;
|
||||||
return rcp;
|
return rcp;
|
||||||
}
|
}
|
||||||
|
|
||||||
RangedPtr<T>& operator+=(size_t inc) {
|
RangedPtr<T>& operator+=(size_t inc) {
|
||||||
this->operator=<T>(*this + inc);
|
*this = *this + inc;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
RangedPtr<T>& operator-=(size_t dec) {
|
RangedPtr<T>& operator-=(size_t dec) {
|
||||||
this->operator=<T>(*this - dec);
|
*this = *this - dec;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
T& operator[](int index) const {
|
T& operator[](int index) const {
|
||||||
MOZ_ASSERT(size_t(index > 0 ? index : -index) <= size_t(-1) / sizeof(T));
|
MOZ_ASSERT(size_t(index > 0 ? index : -index) <= size_t(-1) / sizeof(T));
|
||||||
return *create(ptr + index);
|
return *create(ptr + index);
|
||||||
}
|
}
|
||||||
|
|
||||||
T& operator*() const {
|
T& operator*() const {
|
||||||
return *ptr;
|
return *ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename U>
|
template <typename U>
|
||||||
bool operator==(const RangedPtr<U>& other) const {
|
bool operator==(const RangedPtr<U>& other) const {
|
||||||
return ptr == other.ptr;
|
return ptr == other.ptr;
|
||||||
}
|
}
|
||||||
template <typename U>
|
template <typename U>
|
||||||
bool operator!=(const RangedPtr<U>& other) const {
|
bool operator!=(const RangedPtr<U>& other) const {
|
||||||
return !(*this == other);
|
return !(*this == other);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename U>
|
template<typename U>
|
||||||
bool operator==(const U* u) const {
|
bool operator==(const U* u) const {
|
||||||
return ptr == u;
|
return ptr == u;
|
||||||
}
|
}
|
||||||
template<typename U>
|
template<typename U>
|
||||||
bool operator!=(const U* u) const {
|
bool operator!=(const U* u) const {
|
||||||
return !(*this == u);
|
return !(*this == u);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename U>
|
template <typename U>
|
||||||
bool operator<(const RangedPtr<U>& other) const {
|
bool operator<(const RangedPtr<U>& other) const {
|
||||||
return ptr < other.ptr;
|
return ptr < other.ptr;
|
||||||
}
|
}
|
||||||
template <typename U>
|
template <typename U>
|
||||||
bool operator<=(const RangedPtr<U>& other) const {
|
bool operator<=(const RangedPtr<U>& other) const {
|
||||||
return ptr <= other.ptr;
|
return ptr <= other.ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename U>
|
template <typename U>
|
||||||
bool operator>(const RangedPtr<U>& other) const {
|
bool operator>(const RangedPtr<U>& other) const {
|
||||||
return ptr > other.ptr;
|
return ptr > other.ptr;
|
||||||
}
|
}
|
||||||
template <typename U>
|
template <typename U>
|
||||||
bool operator>=(const RangedPtr<U>& other) const {
|
bool operator>=(const RangedPtr<U>& other) const {
|
||||||
return ptr >= other.ptr;
|
return ptr >= other.ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t operator-(const RangedPtr<T>& other) const {
|
size_t operator-(const RangedPtr<T>& other) const {
|
||||||
MOZ_ASSERT(ptr >= other.ptr);
|
MOZ_ASSERT(ptr >= other.ptr);
|
||||||
return PointerRangeSize(other.ptr, ptr);
|
return PointerRangeSize(other.ptr, ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -1,42 +1,7 @@
|
||||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
/* -*- 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
|
||||||
* ***** BEGIN LICENSE BLOCK *****
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
* 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. */
|
/* Helpers for defining and using refcounted objects. */
|
||||||
|
|
||||||
|
@ -80,24 +45,24 @@ class RefCounted
|
||||||
{
|
{
|
||||||
friend class RefPtr<T>;
|
friend class RefPtr<T>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
RefCounted() : refCnt(0) { }
|
RefCounted() : refCnt(0) { }
|
||||||
~RefCounted() { MOZ_ASSERT(refCnt == -0xdead); }
|
~RefCounted() { MOZ_ASSERT(refCnt == -0xdead); }
|
||||||
|
|
||||||
// Compatibility with nsRefPtr.
|
// Compatibility with nsRefPtr.
|
||||||
void AddRef() {
|
void AddRef() {
|
||||||
MOZ_ASSERT(refCnt >= 0);
|
MOZ_ASSERT(refCnt >= 0);
|
||||||
++refCnt;
|
++refCnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Release() {
|
void Release() {
|
||||||
MOZ_ASSERT(refCnt > 0);
|
MOZ_ASSERT(refCnt > 0);
|
||||||
if (0 == --refCnt) {
|
if (0 == --refCnt) {
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
refCnt = -0xdead;
|
refCnt = -0xdead;
|
||||||
#endif
|
#endif
|
||||||
delete static_cast<T*>(this);
|
delete static_cast<T*>(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compatibility with wtf::RefPtr.
|
// Compatibility with wtf::RefPtr.
|
||||||
|
@ -105,11 +70,11 @@ public:
|
||||||
void deref() { Release(); }
|
void deref() { Release(); }
|
||||||
int refCount() const { return refCnt; }
|
int refCount() const { return refCnt; }
|
||||||
bool hasOneRef() const {
|
bool hasOneRef() const {
|
||||||
MOZ_ASSERT(refCnt > 0);
|
MOZ_ASSERT(refCnt > 0);
|
||||||
return refCnt == 1;
|
return refCnt == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int refCnt;
|
int refCnt;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -130,9 +95,9 @@ class RefPtr
|
||||||
friend class TemporaryRef<T>;
|
friend class TemporaryRef<T>;
|
||||||
friend class OutParamRef<T>;
|
friend class OutParamRef<T>;
|
||||||
|
|
||||||
struct dontRef {};
|
struct DontRef {};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
RefPtr() : ptr(0) { }
|
RefPtr() : ptr(0) { }
|
||||||
RefPtr(const RefPtr& o) : ptr(ref(o.ptr)) {}
|
RefPtr(const RefPtr& o) : ptr(ref(o.ptr)) {}
|
||||||
RefPtr(const TemporaryRef<T>& o) : ptr(o.drop()) {}
|
RefPtr(const TemporaryRef<T>& o) : ptr(o.drop()) {}
|
||||||
|
@ -144,28 +109,28 @@ public:
|
||||||
~RefPtr() { unref(ptr); }
|
~RefPtr() { unref(ptr); }
|
||||||
|
|
||||||
RefPtr& operator=(const RefPtr& o) {
|
RefPtr& operator=(const RefPtr& o) {
|
||||||
assign(ref(o.ptr));
|
assign(ref(o.ptr));
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
RefPtr& operator=(const TemporaryRef<T>& o) {
|
RefPtr& operator=(const TemporaryRef<T>& o) {
|
||||||
assign(o.drop());
|
assign(o.drop());
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
RefPtr& operator=(T* t) {
|
RefPtr& operator=(T* t) {
|
||||||
assign(ref(t));
|
assign(ref(t));
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename U>
|
template<typename U>
|
||||||
RefPtr& operator=(const RefPtr<U>& o) {
|
RefPtr& operator=(const RefPtr<U>& o) {
|
||||||
assign(ref(o.get()));
|
assign(ref(o.get()));
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
TemporaryRef<T> forget() {
|
TemporaryRef<T> forget() {
|
||||||
T* tmp = ptr;
|
T* tmp = ptr;
|
||||||
ptr = 0;
|
ptr = 0;
|
||||||
return TemporaryRef<T>(tmp, dontRef());
|
return TemporaryRef<T>(tmp, DontRef());
|
||||||
}
|
}
|
||||||
|
|
||||||
T* get() const { return ptr; }
|
T* get() const { return ptr; }
|
||||||
|
@ -175,25 +140,23 @@ public:
|
||||||
template<typename U>
|
template<typename U>
|
||||||
operator TemporaryRef<U>() { return TemporaryRef<U>(ptr); }
|
operator TemporaryRef<U>() { return TemporaryRef<U>(ptr); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void assign(T* t) {
|
void assign(T* t) {
|
||||||
unref(ptr);
|
unref(ptr);
|
||||||
ptr = t;
|
ptr = t;
|
||||||
}
|
}
|
||||||
|
|
||||||
T* ptr;
|
T* ptr;
|
||||||
|
|
||||||
static MOZ_ALWAYS_INLINE T* ref(T* t) {
|
static MOZ_ALWAYS_INLINE T* ref(T* t) {
|
||||||
if (t) {
|
if (t)
|
||||||
t->AddRef();
|
t->AddRef();
|
||||||
}
|
return t;
|
||||||
return t;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static MOZ_ALWAYS_INLINE void unref(T* t) {
|
static MOZ_ALWAYS_INLINE void unref(T* t) {
|
||||||
if (t) {
|
if (t)
|
||||||
t->Release();
|
t->Release();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -209,9 +172,9 @@ class TemporaryRef
|
||||||
// To allow it to construct TemporaryRef from a bare T*
|
// To allow it to construct TemporaryRef from a bare T*
|
||||||
friend class RefPtr<T>;
|
friend class RefPtr<T>;
|
||||||
|
|
||||||
typedef typename RefPtr<T>::dontRef dontRef;
|
typedef typename RefPtr<T>::DontRef DontRef;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TemporaryRef(T* t) : ptr(RefPtr<T>::ref(t)) {}
|
TemporaryRef(T* t) : ptr(RefPtr<T>::ref(t)) {}
|
||||||
TemporaryRef(const TemporaryRef& o) : ptr(o.drop()) {}
|
TemporaryRef(const TemporaryRef& o) : ptr(o.drop()) {}
|
||||||
|
|
||||||
|
@ -221,18 +184,18 @@ public:
|
||||||
~TemporaryRef() { RefPtr<T>::unref(ptr); }
|
~TemporaryRef() { RefPtr<T>::unref(ptr); }
|
||||||
|
|
||||||
T* drop() const {
|
T* drop() const {
|
||||||
T* tmp = ptr;
|
T* tmp = ptr;
|
||||||
ptr = 0;
|
ptr = 0;
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TemporaryRef(T* t, const dontRef&) : ptr(t) {}
|
TemporaryRef(T* t, const DontRef&) : ptr(t) {}
|
||||||
|
|
||||||
mutable T* ptr;
|
mutable T* ptr;
|
||||||
|
|
||||||
TemporaryRef();
|
TemporaryRef() MOZ_DELETE;
|
||||||
TemporaryRef& operator=(const TemporaryRef&);
|
void operator=(const TemporaryRef&) MOZ_DELETE;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -254,15 +217,15 @@ class OutParamRef
|
||||||
{
|
{
|
||||||
friend OutParamRef byRef<T>(RefPtr<T>&);
|
friend OutParamRef byRef<T>(RefPtr<T>&);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
~OutParamRef() {
|
~OutParamRef() {
|
||||||
RefPtr<T>::unref(refPtr.ptr);
|
RefPtr<T>::unref(refPtr.ptr);
|
||||||
refPtr.ptr = tmp;
|
refPtr.ptr = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
operator T**() { return &tmp; }
|
operator T**() { return &tmp; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
OutParamRef(RefPtr<T>& p) : refPtr(p), tmp(p.get()) {}
|
OutParamRef(RefPtr<T>& p) : refPtr(p), tmp(p.get()) {}
|
||||||
|
|
||||||
RefPtr<T>& refPtr;
|
RefPtr<T>& refPtr;
|
||||||
|
@ -279,7 +242,7 @@ template<typename T>
|
||||||
OutParamRef<T>
|
OutParamRef<T>
|
||||||
byRef(RefPtr<T>& ptr)
|
byRef(RefPtr<T>& ptr)
|
||||||
{
|
{
|
||||||
return OutParamRef<T>(ptr);
|
return OutParamRef<T>(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
@ -297,15 +260,15 @@ using namespace mozilla;
|
||||||
|
|
||||||
struct Foo : public RefCounted<Foo>
|
struct Foo : public RefCounted<Foo>
|
||||||
{
|
{
|
||||||
Foo() : dead(false) { }
|
Foo() : dead(false) { }
|
||||||
~Foo() {
|
~Foo() {
|
||||||
MOZ_ASSERT(!dead);
|
MOZ_ASSERT(!dead);
|
||||||
dead = true;
|
dead = true;
|
||||||
numDestroyed++;
|
numDestroyed++;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool dead;
|
bool dead;
|
||||||
static int numDestroyed;
|
static int numDestroyed;
|
||||||
};
|
};
|
||||||
int Foo::numDestroyed;
|
int Foo::numDestroyed;
|
||||||
|
|
||||||
|
@ -314,34 +277,34 @@ struct Bar : public Foo { };
|
||||||
TemporaryRef<Foo>
|
TemporaryRef<Foo>
|
||||||
NewFoo()
|
NewFoo()
|
||||||
{
|
{
|
||||||
return RefPtr<Foo>(new Foo());
|
return RefPtr<Foo>(new Foo());
|
||||||
}
|
}
|
||||||
|
|
||||||
TemporaryRef<Foo>
|
TemporaryRef<Foo>
|
||||||
NewBar()
|
NewBar()
|
||||||
{
|
{
|
||||||
return new Bar();
|
return new Bar();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
GetNewFoo(Foo** f)
|
GetNewFoo(Foo** f)
|
||||||
{
|
{
|
||||||
*f = new Bar();
|
*f = new Bar();
|
||||||
// Kids, don't try this at home
|
// Kids, don't try this at home
|
||||||
(*f)->AddRef();
|
(*f)->AddRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
GetPassedFoo(Foo** f)
|
GetPassedFoo(Foo** f)
|
||||||
{
|
{
|
||||||
// Kids, don't try this at home
|
// Kids, don't try this at home
|
||||||
(*f)->AddRef();
|
(*f)->AddRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
GetNewFoo(RefPtr<Foo>* f)
|
GetNewFoo(RefPtr<Foo>* f)
|
||||||
{
|
{
|
||||||
*f = new Bar();
|
*f = new Bar();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -351,93 +314,93 @@ GetPassedFoo(RefPtr<Foo>* f)
|
||||||
TemporaryRef<Foo>
|
TemporaryRef<Foo>
|
||||||
GetNullFoo()
|
GetNullFoo()
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char** argv)
|
main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
// This should blow up
|
// This should blow up
|
||||||
// Foo* f = new Foo(); delete f;
|
// Foo* f = new Foo(); delete f;
|
||||||
|
|
||||||
MOZ_ASSERT(0 == Foo::numDestroyed);
|
MOZ_ASSERT(0 == Foo::numDestroyed);
|
||||||
{
|
{
|
||||||
RefPtr<Foo> f = new Foo();
|
RefPtr<Foo> f = new Foo();
|
||||||
MOZ_ASSERT(f->refCount() == 1);
|
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(1 == Foo::numDestroyed);
|
||||||
|
}
|
||||||
|
MOZ_ASSERT(3 == Foo::numDestroyed);
|
||||||
|
|
||||||
{
|
{
|
||||||
RefPtr<Foo> f1 = NewFoo();
|
RefPtr<Foo> b = NewBar();
|
||||||
RefPtr<Foo> f2(NewFoo());
|
|
||||||
MOZ_ASSERT(1 == Foo::numDestroyed);
|
|
||||||
}
|
|
||||||
MOZ_ASSERT(3 == Foo::numDestroyed);
|
MOZ_ASSERT(3 == Foo::numDestroyed);
|
||||||
|
}
|
||||||
|
MOZ_ASSERT(4 == Foo::numDestroyed);
|
||||||
|
|
||||||
|
{
|
||||||
|
RefPtr<Foo> f1;
|
||||||
{
|
{
|
||||||
RefPtr<Foo> b = NewBar();
|
f1 = new Foo();
|
||||||
MOZ_ASSERT(3 == Foo::numDestroyed);
|
RefPtr<Foo> f2(f1);
|
||||||
|
RefPtr<Foo> f3 = f2;
|
||||||
|
MOZ_ASSERT(4 == Foo::numDestroyed);
|
||||||
}
|
}
|
||||||
MOZ_ASSERT(4 == Foo::numDestroyed);
|
MOZ_ASSERT(4 == Foo::numDestroyed);
|
||||||
|
}
|
||||||
|
MOZ_ASSERT(5 == Foo::numDestroyed);
|
||||||
|
|
||||||
{
|
{
|
||||||
RefPtr<Foo> f1;
|
RefPtr<Foo> f = new Foo();
|
||||||
{
|
f.forget();
|
||||||
f1 = new Foo();
|
MOZ_ASSERT(6 == Foo::numDestroyed);
|
||||||
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();
|
RefPtr<Foo> f = new Foo();
|
||||||
f.forget();
|
GetNewFoo(byRef(f));
|
||||||
MOZ_ASSERT(6 == Foo::numDestroyed);
|
MOZ_ASSERT(7 == Foo::numDestroyed);
|
||||||
}
|
}
|
||||||
|
MOZ_ASSERT(8 == Foo::numDestroyed);
|
||||||
|
|
||||||
{
|
{
|
||||||
RefPtr<Foo> f = new Foo();
|
RefPtr<Foo> f = new Foo();
|
||||||
GetNewFoo(byRef(f));
|
GetPassedFoo(byRef(f));
|
||||||
MOZ_ASSERT(7 == Foo::numDestroyed);
|
|
||||||
}
|
|
||||||
MOZ_ASSERT(8 == Foo::numDestroyed);
|
MOZ_ASSERT(8 == Foo::numDestroyed);
|
||||||
|
}
|
||||||
|
MOZ_ASSERT(9 == Foo::numDestroyed);
|
||||||
|
|
||||||
{
|
{
|
||||||
RefPtr<Foo> f = new Foo();
|
RefPtr<Foo> f = new Foo();
|
||||||
GetPassedFoo(byRef(f));
|
GetNewFoo(&f);
|
||||||
MOZ_ASSERT(8 == Foo::numDestroyed);
|
MOZ_ASSERT(10 == Foo::numDestroyed);
|
||||||
}
|
}
|
||||||
MOZ_ASSERT(9 == Foo::numDestroyed);
|
MOZ_ASSERT(11 == Foo::numDestroyed);
|
||||||
|
|
||||||
{
|
{
|
||||||
RefPtr<Foo> f = new Foo();
|
RefPtr<Foo> f = new Foo();
|
||||||
GetNewFoo(&f);
|
GetPassedFoo(&f);
|
||||||
MOZ_ASSERT(10 == Foo::numDestroyed);
|
|
||||||
}
|
|
||||||
MOZ_ASSERT(11 == Foo::numDestroyed);
|
MOZ_ASSERT(11 == Foo::numDestroyed);
|
||||||
|
}
|
||||||
|
MOZ_ASSERT(12 == Foo::numDestroyed);
|
||||||
|
|
||||||
{
|
{
|
||||||
RefPtr<Foo> f = new Foo();
|
RefPtr<Foo> f1 = new Bar();
|
||||||
GetPassedFoo(&f);
|
}
|
||||||
MOZ_ASSERT(11 == Foo::numDestroyed);
|
MOZ_ASSERT(13 == Foo::numDestroyed);
|
||||||
}
|
|
||||||
MOZ_ASSERT(12 == Foo::numDestroyed);
|
|
||||||
|
|
||||||
{
|
{
|
||||||
RefPtr<Foo> f1 = new Bar();
|
RefPtr<Foo> f = GetNullFoo();
|
||||||
}
|
|
||||||
MOZ_ASSERT(13 == Foo::numDestroyed);
|
MOZ_ASSERT(13 == Foo::numDestroyed);
|
||||||
|
}
|
||||||
|
MOZ_ASSERT(13 == Foo::numDestroyed);
|
||||||
|
|
||||||
{
|
return 0;
|
||||||
RefPtr<Foo> f = GetNullFoo();
|
|
||||||
MOZ_ASSERT(13 == Foo::numDestroyed);
|
|
||||||
}
|
|
||||||
MOZ_ASSERT(13 == Foo::numDestroyed);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -35,12 +35,12 @@
|
||||||
* Note that the RAII classes defined in this header do _not_ perform any form
|
* 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
|
* of reference-counting or garbage-collection. These classes have exactly two
|
||||||
* behaviors:
|
* behaviors:
|
||||||
|
*
|
||||||
* - if |forget()| has not been called, the resource is always deallocated at
|
* - if |forget()| has not been called, the resource is always deallocated at
|
||||||
* the end of the scope;
|
* the end of the scope;
|
||||||
* - if |forget()| has been called, any control on the resource is unbound
|
* - if |forget()| has been called, any control on the resource is unbound
|
||||||
* and the resource is not deallocated by the class.
|
* and the resource is not deallocated by the class.
|
||||||
*
|
*
|
||||||
*
|
|
||||||
* Extension:
|
* Extension:
|
||||||
*
|
*
|
||||||
* In addition, this header provides class |Scoped| and macro |SCOPED_TEMPLATE|
|
* In addition, this header provides class |Scoped| and macro |SCOPED_TEMPLATE|
|
||||||
|
@ -52,6 +52,8 @@
|
||||||
#include "mozilla/Attributes.h"
|
#include "mozilla/Attributes.h"
|
||||||
#include "mozilla/GuardObjects.h"
|
#include "mozilla/GuardObjects.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Scoped is a helper to create RAII wrappers
|
* Scoped is a helper to create RAII wrappers
|
||||||
* Type argument |Traits| is expected to have the following structure:
|
* Type argument |Traits| is expected to have the following structure:
|
||||||
|
@ -66,87 +68,87 @@
|
||||||
* const static void release(type);
|
* const static void release(type);
|
||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
template <typename Traits>
|
template<typename Traits>
|
||||||
class Scoped
|
class Scoped
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef typename Traits::type Resource;
|
typedef typename Traits::type Resource;
|
||||||
|
|
||||||
explicit Scoped(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM)
|
explicit Scoped(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM)
|
||||||
: value(Traits::empty())
|
: value(Traits::empty())
|
||||||
{
|
{
|
||||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||||
}
|
}
|
||||||
explicit Scoped(const Resource& value
|
explicit Scoped(const Resource& value
|
||||||
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
|
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||||
: value(value)
|
: value(value)
|
||||||
{
|
{
|
||||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||||
}
|
}
|
||||||
~Scoped() {
|
~Scoped() {
|
||||||
Traits::release(value);
|
Traits::release(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Constant getter
|
// Constant getter
|
||||||
operator const Resource&() const { return value; }
|
operator const Resource&() const { return value; }
|
||||||
const Resource& operator->() const { return value; }
|
const Resource& operator->() const { return value; }
|
||||||
const Resource& get() const { return value; }
|
const Resource& get() const { return value; }
|
||||||
// Non-constant getter.
|
// Non-constant getter.
|
||||||
Resource& rwget() { return value; }
|
Resource& rwget() { return value; }
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Forget the resource.
|
* Forget the resource.
|
||||||
*
|
*
|
||||||
* Once |forget| has been called, the |Scoped| is neutralized, i.e. it will
|
* 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
|
* have no effect at destruction (unless it is reset to another resource by
|
||||||
* |operator=|).
|
* |operator=|).
|
||||||
*
|
*
|
||||||
* @return The original resource.
|
* @return The original resource.
|
||||||
*/
|
*/
|
||||||
Resource forget() {
|
Resource forget() {
|
||||||
Resource tmp = value;
|
Resource tmp = value;
|
||||||
value = Traits::empty();
|
value = Traits::empty();
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Perform immediate clean-up of this |Scoped|.
|
* Perform immediate clean-up of this |Scoped|.
|
||||||
*
|
*
|
||||||
* If this |Scoped| is currently empty, this method has no effect.
|
* If this |Scoped| is currently empty, this method has no effect.
|
||||||
*/
|
*/
|
||||||
void dispose() {
|
void dispose() {
|
||||||
Traits::release(value);
|
Traits::release(value);
|
||||||
value = Traits::empty();
|
value = Traits::empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==(const Resource& other) const {
|
bool operator==(const Resource& other) const {
|
||||||
return value == other;
|
return value == other;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Replace the resource with another resource.
|
* Replace the resource with another resource.
|
||||||
*
|
*
|
||||||
* Calling |operator=| has the side-effect of triggering clean-up. If you do
|
* Calling |operator=| has the side-effect of triggering clean-up. If you do
|
||||||
* not want to trigger clean-up, you should first invoke |forget|.
|
* not want to trigger clean-up, you should first invoke |forget|.
|
||||||
*
|
*
|
||||||
* @return this
|
* @return this
|
||||||
*/
|
*/
|
||||||
Scoped<Traits>& operator=(const Resource& other) {
|
Scoped<Traits>& operator=(const Resource& other) {
|
||||||
return reset(other);
|
return reset(other);
|
||||||
}
|
}
|
||||||
Scoped<Traits>& reset(const Resource& other) {
|
Scoped<Traits>& reset(const Resource& other) {
|
||||||
Traits::release(value);
|
Traits::release(value);
|
||||||
value = other;
|
value = other;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit Scoped(const Scoped<Traits>& value) MOZ_DELETE;
|
explicit Scoped(const Scoped<Traits>& value) MOZ_DELETE;
|
||||||
Scoped<Traits>& operator=(const Scoped<Traits>& value) MOZ_DELETE;
|
Scoped<Traits>& operator=(const Scoped<Traits>& value) MOZ_DELETE;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Resource value;
|
Resource value;
|
||||||
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
|
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -158,25 +160,25 @@ private:
|
||||||
* for more details.
|
* for more details.
|
||||||
*/
|
*/
|
||||||
#define SCOPED_TEMPLATE(name, Traits) \
|
#define SCOPED_TEMPLATE(name, Traits) \
|
||||||
template <typename Type> \
|
template<typename Type> \
|
||||||
struct name : public Scoped<Traits<Type> > \
|
struct name : public mozilla::Scoped<Traits<Type> > \
|
||||||
{ \
|
{ \
|
||||||
typedef Scoped<Traits<Type> > Super; \
|
typedef mozilla::Scoped<Traits<Type> > Super; \
|
||||||
typedef typename Super::Resource Resource; \
|
typedef typename Super::Resource Resource; \
|
||||||
name& operator=(Resource ptr) { \
|
name& operator=(Resource ptr) { \
|
||||||
Super::operator=(ptr); \
|
Super::operator=(ptr); \
|
||||||
return *this; \
|
return *this; \
|
||||||
} \
|
} \
|
||||||
explicit name(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM) \
|
explicit name(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM) \
|
||||||
: Super(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_TO_PARENT) \
|
: Super(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_TO_PARENT) \
|
||||||
{} \
|
{} \
|
||||||
explicit name(Resource ptr \
|
explicit name(Resource ptr \
|
||||||
MOZ_GUARD_OBJECT_NOTIFIER_PARAM) \
|
MOZ_GUARD_OBJECT_NOTIFIER_PARAM) \
|
||||||
: Super(ptr MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT) \
|
: Super(ptr MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT) \
|
||||||
{} \
|
{} \
|
||||||
private: \
|
private: \
|
||||||
explicit name(name& source) MOZ_DELETE; \
|
explicit name(name& source) MOZ_DELETE; \
|
||||||
name& operator=(name& source) MOZ_DELETE; \
|
name& operator=(name& source) MOZ_DELETE; \
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -186,12 +188,12 @@ private: \
|
||||||
* ScopedFreePtr<S> foo = malloc(sizeof(S));
|
* ScopedFreePtr<S> foo = malloc(sizeof(S));
|
||||||
* ScopedFreePtr<char> bar = strdup(str);
|
* ScopedFreePtr<char> bar = strdup(str);
|
||||||
*/
|
*/
|
||||||
template <typename T>
|
template<typename T>
|
||||||
struct ScopedFreePtrTraits
|
struct ScopedFreePtrTraits
|
||||||
{
|
{
|
||||||
typedef T* type;
|
typedef T* type;
|
||||||
static T* empty() { return NULL; }
|
static T* empty() { return NULL; }
|
||||||
static void release(T* ptr) { free(ptr); }
|
static void release(T* ptr) { free(ptr); }
|
||||||
};
|
};
|
||||||
SCOPED_TEMPLATE(ScopedFreePtr, ScopedFreePtrTraits)
|
SCOPED_TEMPLATE(ScopedFreePtr, ScopedFreePtrTraits)
|
||||||
|
|
||||||
|
@ -201,9 +203,10 @@ SCOPED_TEMPLATE(ScopedFreePtr, ScopedFreePtrTraits)
|
||||||
* struct S { ... };
|
* struct S { ... };
|
||||||
* ScopedDeletePtr<S> foo = new S();
|
* ScopedDeletePtr<S> foo = new S();
|
||||||
*/
|
*/
|
||||||
template <typename T>
|
template<typename T>
|
||||||
struct ScopedDeletePtrTraits : public ScopedFreePtrTraits<T> {
|
struct ScopedDeletePtrTraits : public ScopedFreePtrTraits<T>
|
||||||
static void release(T* ptr) { delete ptr; }
|
{
|
||||||
|
static void release(T* ptr) { delete ptr; }
|
||||||
};
|
};
|
||||||
SCOPED_TEMPLATE(ScopedDeletePtr, ScopedDeletePtrTraits)
|
SCOPED_TEMPLATE(ScopedDeletePtr, ScopedDeletePtrTraits)
|
||||||
|
|
||||||
|
@ -213,12 +216,13 @@ SCOPED_TEMPLATE(ScopedDeletePtr, ScopedDeletePtrTraits)
|
||||||
* struct S { ... };
|
* struct S { ... };
|
||||||
* ScopedDeleteArray<S> foo = new S[42];
|
* ScopedDeleteArray<S> foo = new S[42];
|
||||||
*/
|
*/
|
||||||
template <typename T>
|
template<typename T>
|
||||||
struct ScopedDeleteArrayTraits : public ScopedFreePtrTraits<T>
|
struct ScopedDeleteArrayTraits : public ScopedFreePtrTraits<T>
|
||||||
{
|
{
|
||||||
static void release(T* ptr) { delete [] ptr; }
|
static void release(T* ptr) { delete [] ptr; }
|
||||||
};
|
};
|
||||||
SCOPED_TEMPLATE(ScopedDeleteArray, ScopedDeleteArrayTraits)
|
SCOPED_TEMPLATE(ScopedDeleteArray, ScopedDeleteArrayTraits)
|
||||||
|
|
||||||
|
} /* namespace mozilla */
|
||||||
|
|
||||||
#endif // mozilla_Scoped_h_
|
#endif // mozilla_Scoped_h_
|
||||||
|
|
|
@ -1,42 +1,7 @@
|
||||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
/* -*- 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
|
||||||
* ***** BEGIN LICENSE BLOCK *****
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
* 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. */
|
/* Implements the C99 <stdint.h> interface for C and C++ code. */
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,144 @@
|
||||||
|
/* -*- 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/. */
|
||||||
|
|
||||||
|
/* Cross-platform lightweight thread local data wrappers. */
|
||||||
|
|
||||||
|
#ifndef mozilla_TLS_h_
|
||||||
|
#define mozilla_TLS_h_
|
||||||
|
|
||||||
|
#if defined(XP_WIN)
|
||||||
|
// This file will get included in any file that wants to add a profiler mark.
|
||||||
|
// In order to not bring <windows.h> together we could include windef.h and
|
||||||
|
// winbase.h which are sufficient to get the prototypes for the Tls* functions.
|
||||||
|
// # include <windef.h>
|
||||||
|
// # include <winbase.h>
|
||||||
|
// Unfortunately, even including these headers causes us to add a bunch of ugly
|
||||||
|
// stuff to our namespace e.g #define CreateEvent CreateEventW
|
||||||
|
extern "C" {
|
||||||
|
__declspec(dllimport) void * __stdcall TlsGetValue(unsigned long);
|
||||||
|
__declspec(dllimport) int __stdcall TlsSetValue(unsigned long, void *);
|
||||||
|
__declspec(dllimport) unsigned long __stdcall TlsAlloc();
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
# include <pthread.h>
|
||||||
|
# include <signal.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "mozilla/Assertions.h"
|
||||||
|
#include "mozilla/Attributes.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
|
||||||
|
// sig_safe_t denotes an atomic type which can be read or stored in a single
|
||||||
|
// instruction. This means that data of this type is safe to be manipulated
|
||||||
|
// from a signal handler, or other similar asynchronous execution contexts.
|
||||||
|
#if defined(XP_WIN)
|
||||||
|
typedef unsigned long sig_safe_t;
|
||||||
|
#else
|
||||||
|
typedef sig_atomic_t sig_safe_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Thread Local Storage helpers.
|
||||||
|
*
|
||||||
|
* Usage:
|
||||||
|
*
|
||||||
|
* Only static-storage-duration (e.g. global variables, or static class members)
|
||||||
|
* objects of this class should be instantiated. This class relies on
|
||||||
|
* zero-initialization, which is implicit for static-storage-duration objects.
|
||||||
|
* It doesn't have a custom default constructor, to avoid static initializers.
|
||||||
|
*
|
||||||
|
* API usage:
|
||||||
|
*
|
||||||
|
* // Create a TLS item
|
||||||
|
* mozilla::ThreadLocal<int> tlsKey;
|
||||||
|
* if (!tlsKey.init()) {
|
||||||
|
* // deal with the error
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // Set the TLS value
|
||||||
|
* tlsKey.set(123);
|
||||||
|
*
|
||||||
|
* // Get the TLS value
|
||||||
|
* int value = tlsKey.get();
|
||||||
|
*/
|
||||||
|
template<typename T>
|
||||||
|
class ThreadLocal
|
||||||
|
{
|
||||||
|
#if defined(XP_WIN)
|
||||||
|
typedef unsigned long key_t;
|
||||||
|
#else
|
||||||
|
typedef pthread_key_t key_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
union Helper {
|
||||||
|
void* ptr;
|
||||||
|
T value;
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
MOZ_WARN_UNUSED_RESULT inline bool init();
|
||||||
|
|
||||||
|
inline T get() const;
|
||||||
|
|
||||||
|
inline bool set(const T value);
|
||||||
|
|
||||||
|
bool initialized() const {
|
||||||
|
return inited;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
key_t key;
|
||||||
|
bool inited;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline bool
|
||||||
|
ThreadLocal<T>::init()
|
||||||
|
{
|
||||||
|
MOZ_STATIC_ASSERT(sizeof(T) <= sizeof(void *),
|
||||||
|
"mozilla::ThreadLocal can't be used for types larger than "
|
||||||
|
"a pointer");
|
||||||
|
MOZ_ASSERT(!initialized());
|
||||||
|
#ifdef XP_WIN
|
||||||
|
key = TlsAlloc();
|
||||||
|
inited = key != 0xFFFFFFFFUL; // TLS_OUT_OF_INDEXES
|
||||||
|
#else
|
||||||
|
inited = !pthread_key_create(&key, NULL);
|
||||||
|
#endif
|
||||||
|
return inited;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline T
|
||||||
|
ThreadLocal<T>::get() const
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(initialized());
|
||||||
|
Helper h;
|
||||||
|
#ifdef XP_WIN
|
||||||
|
h.ptr = TlsGetValue(key);
|
||||||
|
#else
|
||||||
|
h.ptr = pthread_getspecific(key);
|
||||||
|
#endif
|
||||||
|
return h.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline bool
|
||||||
|
ThreadLocal<T>::set(const T value)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(initialized());
|
||||||
|
Helper h;
|
||||||
|
h.value = value;
|
||||||
|
#ifdef XP_WIN
|
||||||
|
return TlsSetValue(key, h.ptr);
|
||||||
|
#else
|
||||||
|
return !pthread_setspecific(key, h.ptr);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace mozilla
|
||||||
|
|
||||||
|
#endif // mozilla_TLS_h_
|
|
@ -0,0 +1,122 @@
|
||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
/* Template-based metaprogramming and type-testing facilities. */
|
||||||
|
|
||||||
|
#ifndef mozilla_TypeTraits_h_
|
||||||
|
#define mozilla_TypeTraits_h_
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* IsBaseOf allows to know whether a given class is derived from another.
|
||||||
|
*
|
||||||
|
* Consider the following class definitions:
|
||||||
|
*
|
||||||
|
* class A {};
|
||||||
|
* class B : public A {};
|
||||||
|
* class C {};
|
||||||
|
*
|
||||||
|
* mozilla::IsBaseOf<A, B>::value is true;
|
||||||
|
* mozilla::IsBaseOf<A, C>::value is false;
|
||||||
|
*/
|
||||||
|
template<class Base, class Derived>
|
||||||
|
class IsBaseOf
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
static char test(Base* b);
|
||||||
|
static int test(...);
|
||||||
|
|
||||||
|
public:
|
||||||
|
static const bool value =
|
||||||
|
sizeof(test(static_cast<Derived*>(0))) == sizeof(char);
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* IsConvertible determines whether a value of type From will implicitly convert
|
||||||
|
* to a value of type To. For example:
|
||||||
|
*
|
||||||
|
* struct A {};
|
||||||
|
* struct B : public A {};
|
||||||
|
* struct C {};
|
||||||
|
*
|
||||||
|
* mozilla::IsConvertible<A, A>::value is true;
|
||||||
|
* mozilla::IsConvertible<A*, A*>::value is true;
|
||||||
|
* mozilla::IsConvertible<B, A>::value is true;
|
||||||
|
* mozilla::IsConvertible<B*, A*>::value is true;
|
||||||
|
* mozilla::IsConvertible<C, A>::value is false;
|
||||||
|
* mozilla::IsConvertible<A, C>::value is false;
|
||||||
|
* mozilla::IsConvertible<A*, C*>::value is false;
|
||||||
|
* mozilla::IsConvertible<C*, A*>::value is false.
|
||||||
|
*
|
||||||
|
* For obscure reasons, you can't use IsConvertible when the types being tested
|
||||||
|
* are related through private inheritance, and you'll get a compile error if
|
||||||
|
* you try. Just don't do it!
|
||||||
|
*/
|
||||||
|
template<typename From, typename To>
|
||||||
|
struct IsConvertible
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
static From create();
|
||||||
|
|
||||||
|
template<typename From1, typename To1>
|
||||||
|
static char test(To to);
|
||||||
|
|
||||||
|
template<typename From1, typename To1>
|
||||||
|
static int test(...);
|
||||||
|
|
||||||
|
public:
|
||||||
|
static const bool value =
|
||||||
|
sizeof(test<From, To>(create())) == sizeof(char);
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Conditional selects a class between two, depending on a given boolean value.
|
||||||
|
*
|
||||||
|
* mozilla::Conditional<true, A, B>::Type is A;
|
||||||
|
* mozilla::Conditional<false, A, B>::Type is B;
|
||||||
|
*/
|
||||||
|
template<bool condition, class A, class B>
|
||||||
|
struct Conditional
|
||||||
|
{
|
||||||
|
typedef A Type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class A, class B>
|
||||||
|
struct Conditional<false, A, B>
|
||||||
|
{
|
||||||
|
typedef B Type;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* EnableIf is a struct containing a typedef of T if and only if B is true.
|
||||||
|
*
|
||||||
|
* mozilla::EnableIf<true, int>::Type is int;
|
||||||
|
* mozilla::EnableIf<false, int>::Type is a compile-time error.
|
||||||
|
*
|
||||||
|
* Use this template to implement SFINAE-style (Substitution Failure Is not An
|
||||||
|
* Error) requirements. For example, you might use it to impose a restriction
|
||||||
|
* on a template parameter:
|
||||||
|
*
|
||||||
|
* template<typename T>
|
||||||
|
* class PodVector // vector optimized to store POD (memcpy-able) types
|
||||||
|
* {
|
||||||
|
* EnableIf<IsPodType<T>, T>::Type* vector;
|
||||||
|
* size_t length;
|
||||||
|
* ...
|
||||||
|
* };
|
||||||
|
*/
|
||||||
|
template<bool B, typename T = void>
|
||||||
|
struct EnableIf
|
||||||
|
{};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct EnableIf<true, T>
|
||||||
|
{
|
||||||
|
typedef T Type;
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace mozilla */
|
||||||
|
|
||||||
|
#endif /* mozilla_TypeTraits_h_ */
|
|
@ -1,41 +1,7 @@
|
||||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
/* -*- 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
|
||||||
* ***** BEGIN LICENSE BLOCK *****
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
* 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. */
|
/* mfbt foundational types and macros. */
|
||||||
|
|
||||||
|
|
|
@ -1,41 +1,7 @@
|
||||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
/* -*- 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
|
||||||
* ***** BEGIN LICENSE BLOCK *****
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
* 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
|
* Miscellaneous uncategorized functionality. Please add new functionality to
|
||||||
|
@ -54,54 +20,53 @@
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DebugOnly contains a value of type T, but only in debug builds. In
|
* DebugOnly contains a value of type T, but only in debug builds. In release
|
||||||
* release builds, it does not contain a value. This helper is
|
* builds, it does not contain a value. This helper is intended to be used with
|
||||||
* intended to be used along with ASSERT()-style macros, allowing one
|
* MOZ_ASSERT()-style macros, allowing one to write:
|
||||||
* to write
|
|
||||||
*
|
*
|
||||||
* DebugOnly<bool> check = Func();
|
* DebugOnly<bool> check = func();
|
||||||
* ASSERT(check);
|
* MOZ_ASSERT(check);
|
||||||
*
|
*
|
||||||
* more concisely than declaring |check| conditional on #ifdef DEBUG,
|
* more concisely than declaring |check| conditional on #ifdef DEBUG, but also
|
||||||
* but also without allocating storage space for |check| in release
|
* without allocating storage space for |check| in release builds.
|
||||||
* builds.
|
|
||||||
*
|
*
|
||||||
* DebugOnly instances can only be coerced to T in debug builds; in
|
* DebugOnly instances can only be coerced to T in debug builds. In release
|
||||||
* release builds, they don't have a value so type coercion is not
|
* builds they don't have a value, so type coercion is not well defined.
|
||||||
* well defined.
|
|
||||||
*/
|
*/
|
||||||
template <typename T>
|
template<typename T>
|
||||||
struct DebugOnly
|
struct DebugOnly
|
||||||
{
|
{
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
T value;
|
T value;
|
||||||
|
|
||||||
DebugOnly() {}
|
DebugOnly() { }
|
||||||
DebugOnly(const T& other) : value(other) {}
|
DebugOnly(const T& other) : value(other) { }
|
||||||
DebugOnly(const DebugOnly& other) : value(other.value) {}
|
DebugOnly(const DebugOnly& other) : value(other.value) { }
|
||||||
DebugOnly& operator=(const T& rhs) {
|
DebugOnly& operator=(const T& rhs) {
|
||||||
value = rhs;
|
value = rhs;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
void operator++(int) {
|
void operator++(int) {
|
||||||
value++;
|
value++;
|
||||||
}
|
}
|
||||||
void operator--(int) {
|
void operator--(int) {
|
||||||
value--;
|
value--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
T *operator&() { return &value; }
|
||||||
|
|
||||||
operator T&() { return value; }
|
operator T&() { return value; }
|
||||||
operator const T&() const { return value; }
|
operator const T&() const { return value; }
|
||||||
|
|
||||||
T& operator->() { return value; }
|
T& operator->() { return value; }
|
||||||
|
|
||||||
#else
|
#else
|
||||||
DebugOnly() {}
|
DebugOnly() { }
|
||||||
DebugOnly(const T&) {}
|
DebugOnly(const T&) { }
|
||||||
DebugOnly(const DebugOnly&) {}
|
DebugOnly(const DebugOnly&) { }
|
||||||
DebugOnly& operator=(const T&) { return *this; }
|
DebugOnly& operator=(const T&) { return *this; }
|
||||||
void operator++(int) {}
|
void operator++(int) { }
|
||||||
void operator--(int) {}
|
void operator--(int) { }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -117,17 +82,16 @@ struct DebugOnly
|
||||||
* bytes of alignment a given type needs.
|
* bytes of alignment a given type needs.
|
||||||
*/
|
*/
|
||||||
template<class T>
|
template<class T>
|
||||||
struct AlignmentFinder
|
class AlignmentFinder
|
||||||
{
|
{
|
||||||
private:
|
struct Aligner
|
||||||
struct Aligner
|
{
|
||||||
{
|
char c;
|
||||||
char c;
|
T t;
|
||||||
T t;
|
};
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static const int alignment = sizeof(Aligner) - sizeof(T);
|
static const size_t alignment = sizeof(Aligner) - sizeof(T);
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MOZ_ALIGNOF(T) mozilla::AlignmentFinder<T>::alignment
|
#define MOZ_ALIGNOF(T) mozilla::AlignmentFinder<T>::alignment
|
||||||
|
@ -154,7 +118,8 @@ public:
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* AlignedElem<N> is a structure whose alignment is guaranteed to be at least N bytes.
|
* 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.
|
* We support 1, 2, 4, 8, and 16-bit alignment.
|
||||||
*/
|
*/
|
||||||
|
@ -169,31 +134,31 @@ struct AlignedElem;
|
||||||
template<>
|
template<>
|
||||||
struct AlignedElem<1>
|
struct AlignedElem<1>
|
||||||
{
|
{
|
||||||
MOZ_ALIGNED_DECL(uint8_t elem, 1);
|
MOZ_ALIGNED_DECL(uint8_t elem, 1);
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct AlignedElem<2>
|
struct AlignedElem<2>
|
||||||
{
|
{
|
||||||
MOZ_ALIGNED_DECL(uint8_t elem, 2);
|
MOZ_ALIGNED_DECL(uint8_t elem, 2);
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct AlignedElem<4>
|
struct AlignedElem<4>
|
||||||
{
|
{
|
||||||
MOZ_ALIGNED_DECL(uint8_t elem, 4);
|
MOZ_ALIGNED_DECL(uint8_t elem, 4);
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct AlignedElem<8>
|
struct AlignedElem<8>
|
||||||
{
|
{
|
||||||
MOZ_ALIGNED_DECL(uint8_t elem, 8);
|
MOZ_ALIGNED_DECL(uint8_t elem, 8);
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct AlignedElem<16>
|
struct AlignedElem<16>
|
||||||
{
|
{
|
||||||
MOZ_ALIGNED_DECL(uint8_t elem, 16);
|
MOZ_ALIGNED_DECL(uint8_t elem, 16);
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -206,28 +171,28 @@ struct AlignedElem<16>
|
||||||
* false negatives when we cast from the char buffer to whatever type we've
|
* false negatives when we cast from the char buffer to whatever type we've
|
||||||
* constructed using the bytes.
|
* constructed using the bytes.
|
||||||
*/
|
*/
|
||||||
template <size_t nbytes>
|
template<size_t nbytes>
|
||||||
struct AlignedStorage
|
struct AlignedStorage
|
||||||
{
|
{
|
||||||
union U {
|
union U {
|
||||||
char bytes[nbytes];
|
char bytes[nbytes];
|
||||||
uint64_t _;
|
uint64_t _;
|
||||||
} u;
|
} u;
|
||||||
|
|
||||||
const void *addr() const { return u.bytes; }
|
const void* addr() const { return u.bytes; }
|
||||||
void *addr() { return u.bytes; }
|
void* addr() { return u.bytes; }
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class T>
|
template<class T>
|
||||||
struct AlignedStorage2
|
struct AlignedStorage2
|
||||||
{
|
{
|
||||||
union U {
|
union U {
|
||||||
char bytes[sizeof(T)];
|
char bytes[sizeof(T)];
|
||||||
uint64_t _;
|
uint64_t _;
|
||||||
} u;
|
} u;
|
||||||
|
|
||||||
const T *addr() const { return (const T *)u.bytes; }
|
const T* addr() const { return reinterpret_cast<const T*>(u.bytes); }
|
||||||
T *addr() { return (T *)(void *)u.bytes; }
|
T* addr() { return static_cast<T*>(static_cast<void*>(u.bytes)); }
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -241,16 +206,13 @@ struct AlignedStorage2
|
||||||
* N.B. GCC seems to miss some optimizations with Maybe and may generate extra
|
* N.B. GCC seems to miss some optimizations with Maybe and may generate extra
|
||||||
* branches/loads/stores. Use with caution on hot paths.
|
* branches/loads/stores. Use with caution on hot paths.
|
||||||
*/
|
*/
|
||||||
template <class T>
|
template<class T>
|
||||||
class Maybe
|
class Maybe
|
||||||
{
|
{
|
||||||
AlignedStorage2<T> storage;
|
AlignedStorage2<T> storage;
|
||||||
bool constructed;
|
bool constructed;
|
||||||
|
|
||||||
T &asT() { return *storage.addr(); }
|
T& asT() { return *storage.addr(); }
|
||||||
|
|
||||||
explicit Maybe(const Maybe &other);
|
|
||||||
const Maybe &operator=(const Maybe &other);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Maybe() { constructed = false; }
|
Maybe() { constructed = false; }
|
||||||
|
@ -259,63 +221,67 @@ class Maybe
|
||||||
bool empty() const { return !constructed; }
|
bool empty() const { return !constructed; }
|
||||||
|
|
||||||
void construct() {
|
void construct() {
|
||||||
MOZ_ASSERT(!constructed);
|
MOZ_ASSERT(!constructed);
|
||||||
new(storage.addr()) T();
|
new (storage.addr()) T();
|
||||||
constructed = true;
|
constructed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T1>
|
template<class T1>
|
||||||
void construct(const T1 &t1) {
|
void construct(const T1& t1) {
|
||||||
MOZ_ASSERT(!constructed);
|
MOZ_ASSERT(!constructed);
|
||||||
new(storage.addr()) T(t1);
|
new (storage.addr()) T(t1);
|
||||||
constructed = true;
|
constructed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T1, class T2>
|
template<class T1, class T2>
|
||||||
void construct(const T1 &t1, const T2 &t2) {
|
void construct(const T1& t1, const T2& t2) {
|
||||||
MOZ_ASSERT(!constructed);
|
MOZ_ASSERT(!constructed);
|
||||||
new(storage.addr()) T(t1, t2);
|
new (storage.addr()) T(t1, t2);
|
||||||
constructed = true;
|
constructed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T1, class T2, class T3>
|
template<class T1, class T2, class T3>
|
||||||
void construct(const T1 &t1, const T2 &t2, const T3 &t3) {
|
void construct(const T1& t1, const T2& t2, const T3& t3) {
|
||||||
MOZ_ASSERT(!constructed);
|
MOZ_ASSERT(!constructed);
|
||||||
new(storage.addr()) T(t1, t2, t3);
|
new (storage.addr()) T(t1, t2, t3);
|
||||||
constructed = true;
|
constructed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T1, class T2, class T3, class T4>
|
template<class T1, class T2, class T3, class T4>
|
||||||
void construct(const T1 &t1, const T2 &t2, const T3 &t3, const T4 &t4) {
|
void construct(const T1& t1, const T2& t2, const T3& t3, const T4& t4) {
|
||||||
MOZ_ASSERT(!constructed);
|
MOZ_ASSERT(!constructed);
|
||||||
new(storage.addr()) T(t1, t2, t3, t4);
|
new (storage.addr()) T(t1, t2, t3, t4);
|
||||||
constructed = true;
|
constructed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
T *addr() {
|
T* addr() {
|
||||||
MOZ_ASSERT(constructed);
|
MOZ_ASSERT(constructed);
|
||||||
return &asT();
|
return &asT();
|
||||||
}
|
}
|
||||||
|
|
||||||
T &ref() {
|
T& ref() {
|
||||||
MOZ_ASSERT(constructed);
|
MOZ_ASSERT(constructed);
|
||||||
return asT();
|
return asT();
|
||||||
}
|
}
|
||||||
|
|
||||||
const T &ref() const {
|
const T& ref() const {
|
||||||
MOZ_ASSERT(constructed);
|
MOZ_ASSERT(constructed);
|
||||||
return const_cast<Maybe *>(this)->asT();
|
return const_cast<Maybe*>(this)->asT();
|
||||||
}
|
}
|
||||||
|
|
||||||
void destroy() {
|
void destroy() {
|
||||||
ref().~T();
|
ref().~T();
|
||||||
constructed = false;
|
constructed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void destroyIfConstructed() {
|
void destroyIfConstructed() {
|
||||||
if (!empty())
|
if (!empty())
|
||||||
destroy();
|
destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Maybe(const Maybe& other) MOZ_DELETE;
|
||||||
|
const Maybe& operator=(const Maybe& other) MOZ_DELETE;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -324,12 +290,12 @@ class Maybe
|
||||||
* set, the unsigned subtraction followed by right shift will produce -1, or
|
* set, the unsigned subtraction followed by right shift will produce -1, or
|
||||||
* size_t(-1), instead of the real difference.
|
* size_t(-1), instead of the real difference.
|
||||||
*/
|
*/
|
||||||
template <class T>
|
template<class T>
|
||||||
MOZ_ALWAYS_INLINE size_t
|
MOZ_ALWAYS_INLINE size_t
|
||||||
PointerRangeSize(T* begin, T* end)
|
PointerRangeSize(T* begin, T* end)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(end >= begin);
|
MOZ_ASSERT(end >= begin);
|
||||||
return (size_t(end) - size_t(begin)) / sizeof(T);
|
return (size_t(end) - size_t(begin)) / sizeof(T);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -342,7 +308,7 @@ template<typename T, size_t N>
|
||||||
size_t
|
size_t
|
||||||
ArrayLength(T (&arr)[N])
|
ArrayLength(T (&arr)[N])
|
||||||
{
|
{
|
||||||
return N;
|
return N;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -354,7 +320,7 @@ template<typename T, size_t N>
|
||||||
T*
|
T*
|
||||||
ArrayEnd(T (&arr)[N])
|
ArrayEnd(T (&arr)[N])
|
||||||
{
|
{
|
||||||
return arr + ArrayLength(arr);
|
return arr + ArrayLength(arr);
|
||||||
}
|
}
|
||||||
|
|
||||||
} /* namespace mozilla */
|
} /* namespace mozilla */
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
b55240db62f4497ae539c524d8a5ed2efb2a6b48
|
4b6a92efb0e694d8aee845c9c7fcd1c2e63adab6
|
Loading…
Reference in New Issue