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 -*-
|
||||
* vim: set ts=4 sw=4 et tw=99 ft=cpp:
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is SpiderMonkey JavaScript engine.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Terrence Cole <terrence@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
* 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 BitArray_h__
|
||||
#define BitArray_h__
|
||||
|
|
|
@ -1,48 +1,16 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sw=4 et tw=78:
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is SpiderMonkey global object code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* the Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
* 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 jsgc_barrier_h___
|
||||
#define jsgc_barrier_h___
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "jscell.h"
|
||||
|
||||
#include "gc/Heap.h"
|
||||
#include "js/HashTable.h"
|
||||
|
||||
/*
|
||||
|
@ -140,12 +108,10 @@
|
|||
* and jsid, respectively.
|
||||
*
|
||||
* One additional note: not all object writes need to be barriered. Writes to
|
||||
* newly allocated objects do not need a barrier as long as the GC is not
|
||||
* allowed to run in between the allocation and the write. In these cases, we
|
||||
* use the "obj->field.init(value)" method instead of "obj->field = value".
|
||||
* We use the init naming idiom in many places to signify that a field is being
|
||||
* assigned for the first time, and that no GCs have taken place between the
|
||||
* object allocation and the assignment.
|
||||
* newly allocated objects do not need a pre-barrier. In these cases, we use
|
||||
* the "obj->field.init(value)" method instead of "obj->field = value". We use
|
||||
* the init naming idiom in many places to signify that a field is being
|
||||
* assigned for the first time.
|
||||
*/
|
||||
|
||||
struct JSXML;
|
||||
|
@ -153,31 +119,39 @@ struct JSXML;
|
|||
namespace js {
|
||||
|
||||
template<class T, typename Unioned = uintptr_t>
|
||||
class HeapPtr
|
||||
class EncapsulatedPtr
|
||||
{
|
||||
protected:
|
||||
union {
|
||||
T *value;
|
||||
Unioned other;
|
||||
};
|
||||
|
||||
public:
|
||||
HeapPtr() : value(NULL) {}
|
||||
explicit HeapPtr(T *v) : value(v) { post(); }
|
||||
explicit HeapPtr(const HeapPtr<T> &v) : value(v.value) { post(); }
|
||||
EncapsulatedPtr() : value(NULL) {}
|
||||
explicit EncapsulatedPtr(T *v) : value(v) {}
|
||||
explicit EncapsulatedPtr(const EncapsulatedPtr<T> &v) : value(v.value) {}
|
||||
|
||||
~HeapPtr() { pre(); }
|
||||
|
||||
/* Use this to install a ptr into a newly allocated object. */
|
||||
void init(T *v) {
|
||||
JS_ASSERT(!IsPoisonedPtr<T>(v));
|
||||
value = v;
|
||||
post();
|
||||
}
|
||||
~EncapsulatedPtr() { pre(); }
|
||||
|
||||
/* Use to set the pointer to NULL. */
|
||||
void clear() {
|
||||
pre();
|
||||
value = NULL;
|
||||
pre();
|
||||
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. */
|
||||
|
@ -192,30 +166,48 @@ class HeapPtr
|
|||
|
||||
Unioned *unsafeGetUnioned() { return &other; }
|
||||
|
||||
HeapPtr<T, Unioned> &operator=(T *v) {
|
||||
pre();
|
||||
JS_ASSERT(!IsPoisonedPtr<T>(v));
|
||||
value = v;
|
||||
post();
|
||||
return *this;
|
||||
}
|
||||
|
||||
HeapPtr<T, Unioned> &operator=(const HeapPtr<T> &v) {
|
||||
pre();
|
||||
JS_ASSERT(!IsPoisonedPtr<T>(v.value));
|
||||
value = v.value;
|
||||
post();
|
||||
return *this;
|
||||
}
|
||||
|
||||
T &operator*() const { return *value; }
|
||||
T *operator->() const { return value; }
|
||||
|
||||
operator T*() const { return value; }
|
||||
|
||||
private:
|
||||
protected:
|
||||
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(). */
|
||||
template<class T1, class T2>
|
||||
|
@ -225,6 +217,41 @@ class HeapPtr
|
|||
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
|
||||
* barriers with only one branch to check if we're in an incremental GC.
|
||||
|
@ -249,7 +276,9 @@ struct Shape;
|
|||
class BaseShape;
|
||||
namespace types { struct TypeObject; }
|
||||
|
||||
typedef HeapPtr<JSAtom> HeapPtrAtom;
|
||||
typedef RelocatablePtr<JSObject> RelocatablePtrObject;
|
||||
typedef RelocatablePtr<JSScript> RelocatablePtrScript;
|
||||
|
||||
typedef HeapPtr<JSObject> HeapPtrObject;
|
||||
typedef HeapPtr<JSFunction> HeapPtrFunction;
|
||||
typedef HeapPtr<JSString> HeapPtrString;
|
||||
|
@ -272,9 +301,9 @@ struct HeapPtrHasher
|
|||
|
||||
/* Specialized hashing policy for HeapPtrs. */
|
||||
template <class T>
|
||||
struct DefaultHasher< HeapPtr<T> >: HeapPtrHasher<T> { };
|
||||
struct DefaultHasher< HeapPtr<T> > : HeapPtrHasher<T> { };
|
||||
|
||||
class EncapsulatedValue
|
||||
class EncapsulatedValue : public ValueOperations<EncapsulatedValue>
|
||||
{
|
||||
protected:
|
||||
Value value;
|
||||
|
@ -292,47 +321,27 @@ class EncapsulatedValue
|
|||
~EncapsulatedValue() {}
|
||||
|
||||
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; }
|
||||
Value *unsafeGet() { return &value; }
|
||||
operator const Value &() const { return value; }
|
||||
|
||||
bool isUndefined() const { return value.isUndefined(); }
|
||||
bool isNull() const { return value.isNull(); }
|
||||
bool isBoolean() const { return value.isBoolean(); }
|
||||
bool isTrue() const { return value.isTrue(); }
|
||||
bool isFalse() const { return value.isFalse(); }
|
||||
bool isNumber() const { return value.isNumber(); }
|
||||
bool isInt32() const { return value.isInt32(); }
|
||||
bool isDouble() const { return value.isDouble(); }
|
||||
bool isString() const { return value.isString(); }
|
||||
bool isObject() const { return value.isObject(); }
|
||||
bool isMagic(JSWhyMagic why) const { return value.isMagic(why); }
|
||||
bool isGCThing() const { return value.isGCThing(); }
|
||||
bool isMarkable() const { return value.isMarkable(); }
|
||||
|
||||
bool toBoolean() const { return value.toBoolean(); }
|
||||
double toNumber() const { return value.toNumber(); }
|
||||
int32_t toInt32() const { return value.toInt32(); }
|
||||
double toDouble() const { return value.toDouble(); }
|
||||
JSString *toString() const { return value.toString(); }
|
||||
JSObject &toObject() const { return value.toObject(); }
|
||||
JSObject *toObjectOrNull() const { return value.toObjectOrNull(); }
|
||||
void *toGCThing() const { return value.toGCThing(); }
|
||||
|
||||
JSGCTraceKind gcKind() const { return value.gcKind(); }
|
||||
|
||||
uint64_t asRawBits() const { return value.asRawBits(); }
|
||||
|
||||
#ifdef DEBUG
|
||||
JSWhyMagic whyMagic() const { return value.whyMagic(); }
|
||||
#endif
|
||||
|
||||
static inline void writeBarrierPre(const Value &v);
|
||||
static inline void writeBarrierPre(JSCompartment *comp, const Value &v);
|
||||
|
||||
protected:
|
||||
inline void pre();
|
||||
inline void pre(JSCompartment *comp);
|
||||
|
||||
private:
|
||||
friend class ValueOperations<EncapsulatedValue>;
|
||||
const Value * extract() const { return &value; }
|
||||
};
|
||||
|
||||
class HeapValue : public EncapsulatedValue
|
||||
|
@ -357,14 +366,31 @@ class HeapValue : public EncapsulatedValue
|
|||
*/
|
||||
inline void set(JSCompartment *comp, const Value &v);
|
||||
|
||||
static inline void writeBarrierPost(const Value &v, void *addr);
|
||||
static inline void writeBarrierPost(JSCompartment *comp, const Value &v, void *addr);
|
||||
static inline void writeBarrierPost(const Value &v, Value *addr);
|
||||
static inline void writeBarrierPost(JSCompartment *comp, const Value &v, Value *addr);
|
||||
|
||||
private:
|
||||
inline void post();
|
||||
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
|
||||
{
|
||||
/*
|
||||
|
@ -401,7 +427,7 @@ class HeapSlot : public EncapsulatedValue
|
|||
* Run a post write barrier that encompasses multiple contiguous slots in a
|
||||
* single step.
|
||||
*/
|
||||
static inline void
|
||||
inline void
|
||||
SlotRangeWriteBarrierPost(JSCompartment *comp, JSObject *obj, uint32_t start, uint32_t count)
|
||||
{
|
||||
}
|
||||
|
@ -414,6 +440,14 @@ Valueify(const EncapsulatedValue *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
|
||||
{
|
||||
HeapSlot *array;
|
||||
|
@ -428,21 +462,20 @@ class HeapSlotArray
|
|||
HeapSlotArray operator +(uint32_t offset) const { return HeapSlotArray(array + offset); }
|
||||
};
|
||||
|
||||
class HeapId
|
||||
class EncapsulatedId
|
||||
{
|
||||
protected:
|
||||
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:
|
||||
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; }
|
||||
|
||||
|
@ -450,11 +483,37 @@ class HeapId
|
|||
jsid *unsafeGet() { return &value; }
|
||||
operator jsid() const { return value; }
|
||||
|
||||
private:
|
||||
protected:
|
||||
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();
|
||||
|
||||
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 *unsafeGet() { return value; }
|
||||
T **unsafeGet() { return &value; }
|
||||
|
||||
void set(T *v) { value = v; }
|
||||
|
||||
|
@ -504,6 +563,7 @@ class ReadBarrieredValue
|
|||
ReadBarrieredValue(const Value &value) : value(value) {}
|
||||
|
||||
inline const Value &get() const;
|
||||
Value *unsafeGet() { return &value; }
|
||||
inline operator const Value &() const;
|
||||
|
||||
inline JSObject &toObject() const;
|
||||
|
@ -511,11 +571,11 @@ class ReadBarrieredValue
|
|||
|
||||
namespace tl {
|
||||
|
||||
template <class T> struct IsPostBarrieredType<HeapPtr<T> > {
|
||||
static const bool result = true; };
|
||||
template <> struct IsPostBarrieredType<HeapSlot> { static const bool result = true; };
|
||||
template <> struct IsPostBarrieredType<HeapValue> { static const bool result = true; };
|
||||
template <> struct IsPostBarrieredType<HeapId> { static const bool result = true; };
|
||||
template <class T> struct IsRelocatableHeapType<HeapPtr<T> >
|
||||
{ static const bool result = false; };
|
||||
template <> struct IsRelocatableHeapType<HeapSlot> { static const bool result = false; };
|
||||
template <> struct IsRelocatableHeapType<HeapValue> { static const bool result = false; };
|
||||
template <> struct IsRelocatableHeapType<HeapId> { static const bool result = false; };
|
||||
|
||||
} /* namespace tl */
|
||||
} /* 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 -*-
|
||||
* vim: set ts=8 sw=4 et tw=78:
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is SpiderMonkey global object code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* the Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2012
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
* 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 jsgc_root_h__
|
||||
#define jsgc_root_h__
|
||||
|
||||
#include "jspubtd.h"
|
||||
|
||||
#include "js/Utility.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include "mozilla/TypeTraits.h"
|
||||
|
||||
#include "jsapi.h"
|
||||
|
||||
#include "js/TemplateLib.h"
|
||||
#include "js/Utility.h"
|
||||
|
||||
namespace JS {
|
||||
|
||||
/*
|
||||
|
@ -76,75 +47,159 @@ namespace JS {
|
|||
* on the type T of the value being rooted, for which RootMethods<T> must
|
||||
* have an instantiation.
|
||||
*
|
||||
* - Root<T> roots an existing stack allocated variable or other location of
|
||||
* type T. This is typically used either when a variable only needs to be
|
||||
* rooted on certain rare paths, or when a function takes a bare GC thing
|
||||
* pointer as an argument and needs to root it. In the latter case a
|
||||
* Handle<T> is generally preferred, see below.
|
||||
* - Rooted<T> declares a variable of type T, whose value is always rooted.
|
||||
* Rooted<T> may be automatically coerced to a Handle<T>, below. Rooted<T>
|
||||
* should be used whenever a local variable's value may be held live across a
|
||||
* call which can allocate GC things or otherwise trigger a GC.
|
||||
*
|
||||
* - RootedVar<T> declares a variable of type T, whose value is always rooted.
|
||||
*
|
||||
* - Handle<T> is a const reference to a Root<T> or RootedVar<T>. Handles are
|
||||
* coerced automatically from such a Root<T> or RootedVar<T>. Functions which
|
||||
* take GC things or values as arguments and need to root those arguments
|
||||
* should generally replace those arguments with handles and avoid any
|
||||
* explicit rooting. This has two benefits. First, when several such
|
||||
* functions call each other then redundant rooting of multiple copies of the
|
||||
* GC thing can be avoided. Second, if the caller does not pass a rooted
|
||||
* value a compile error will be generated, which is quicker and easier to
|
||||
* fix than when relying on a separate rooting analysis.
|
||||
* - 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
|
||||
* generally use handles for those arguments and avoid any explicit rooting.
|
||||
* This has two benefits. First, when several such functions call each other
|
||||
* then redundant rooting of multiple copies of the GC thing can be avoided.
|
||||
* Second, if the caller does not pass a rooted value a compile error will be
|
||||
* generated, which is quicker and easier to fix than when relying on a
|
||||
* separate rooting analysis.
|
||||
*/
|
||||
|
||||
template <typename T> class Root;
|
||||
template <typename T> class RootedVar;
|
||||
template <typename T> class Rooted;
|
||||
|
||||
template <typename T>
|
||||
struct RootMethods { };
|
||||
|
||||
/*
|
||||
* Reference to a stack location rooted for GC. See the "Moving GC Stack
|
||||
* Rooting" comment above.
|
||||
* Handle provides an implicit constructor for NullPtr so that, given:
|
||||
* 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>
|
||||
class Handle
|
||||
class Handle : public HandleBase<T>
|
||||
{
|
||||
public:
|
||||
/* Copy handles of different types, with implicit coercion. */
|
||||
template <typename S> Handle(Handle<S> handle) {
|
||||
testAssign<S>();
|
||||
/* Creates a handle from a handle of a type convertible to T. */
|
||||
template <typename S>
|
||||
Handle(Handle<S> handle,
|
||||
typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type dummy = 0)
|
||||
{
|
||||
ptr = reinterpret_cast<const T *>(handle.address());
|
||||
}
|
||||
|
||||
/* Get a handle from a rooted stack location, with implicit coercion. */
|
||||
template <typename S> inline Handle(const Root<S> &root);
|
||||
template <typename S> inline Handle(const RootedVar<S> &root);
|
||||
/* Create a handle for a NULL pointer. */
|
||||
Handle(NullPtr) {
|
||||
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:
|
||||
Handle() {}
|
||||
|
||||
const T *ptr;
|
||||
T value() { return *ptr; }
|
||||
|
||||
template <typename S>
|
||||
void testAssign() {
|
||||
#ifdef DEBUG
|
||||
T a = RootMethods<T>::initial();
|
||||
S b = RootMethods<S>::initial();
|
||||
a = b;
|
||||
(void)a;
|
||||
#endif
|
||||
}
|
||||
void operator =(S v) MOZ_DELETE;
|
||||
};
|
||||
|
||||
typedef Handle<JSObject*> HandleObject;
|
||||
typedef Handle<JSFunction*> HandleFunction;
|
||||
typedef Handle<JSScript*> HandleScript;
|
||||
typedef Handle<JSString*> HandleString;
|
||||
typedef Handle<jsid> HandleId;
|
||||
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>
|
||||
struct RootMethods<T *>
|
||||
{
|
||||
|
@ -153,76 +208,103 @@ struct RootMethods<T *>
|
|||
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
|
||||
* and ensures that throughout its lifetime the referenced variable
|
||||
* will remain pinned against a moving GC.
|
||||
* Local variable of type T whose value is always rooted. This is typically
|
||||
* used for local variables, or for non-rooted values being passed to a
|
||||
* 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
|
||||
* initialized, as otherwise the GC may try to use the the uninitialized value.
|
||||
* It is generally preferable to use either RootedVar for local variables, or
|
||||
* Handle for arguments.
|
||||
* If you want to add additional methods to Rooted for a specific
|
||||
* specialization, define a RootedBase<T> specialization containing them.
|
||||
*/
|
||||
template <typename T>
|
||||
class Root
|
||||
class Rooted : public RootedBase<T>
|
||||
{
|
||||
public:
|
||||
Root(JSContext *cx_, const T *ptr
|
||||
JS_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
void init(JSContext *cx_)
|
||||
{
|
||||
#ifdef JSGC_ROOT_ANALYSIS
|
||||
#if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)
|
||||
ContextFriendFields *cx = ContextFriendFields::get(cx_);
|
||||
|
||||
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;
|
||||
*stack = this;
|
||||
|
||||
JS_ASSERT(!RootMethods<T>::poisoned(ptr));
|
||||
#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);
|
||||
*stack = prev;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef JSGC_ROOT_ANALYSIS
|
||||
Root<T> *previous() { return prev; }
|
||||
#if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)
|
||||
Rooted<T> *previous() { return prev; }
|
||||
#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:
|
||||
|
||||
#ifdef JSGC_ROOT_ANALYSIS
|
||||
Root<T> **stack, *prev;
|
||||
#if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)
|
||||
Rooted<T> **stack, *prev;
|
||||
#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>
|
||||
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());
|
||||
}
|
||||
|
||||
typedef Root<JSObject*> RootObject;
|
||||
typedef Root<JSFunction*> RootFunction;
|
||||
typedef Root<JSString*> RootString;
|
||||
typedef Root<jsid> RootId;
|
||||
typedef Root<Value> RootValue;
|
||||
template<typename T> template <typename S>
|
||||
inline
|
||||
MutableHandle<T>::MutableHandle(Rooted<S> *root,
|
||||
typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type dummy)
|
||||
{
|
||||
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
|
||||
|
@ -238,18 +320,30 @@ class SkipRoot
|
|||
const uint8_t *start;
|
||||
const uint8_t *end;
|
||||
|
||||
public:
|
||||
template <typename T>
|
||||
SkipRoot(JSContext *cx_, const T *ptr
|
||||
JS_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
void init(ContextFriendFields *cx, const T *ptr, size_t count)
|
||||
{
|
||||
ContextFriendFields *cx = ContextFriendFields::get(cx_);
|
||||
|
||||
this->stack = &cx->skipGCRooters;
|
||||
this->prev = *stack;
|
||||
*stack = this;
|
||||
this->start = (const uint8_t *) ptr;
|
||||
this->end = this->start + sizeof(T);
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -275,74 +369,66 @@ class SkipRoot
|
|||
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 */
|
||||
|
||||
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||
};
|
||||
|
||||
/* Make a local variable which stays rooted throughout its lifetime. */
|
||||
template <typename T>
|
||||
class RootedVar
|
||||
{
|
||||
public:
|
||||
RootedVar(JSContext *cx)
|
||||
: ptr(RootMethods<T>::initial()), root(cx, &ptr)
|
||||
{}
|
||||
#ifdef DEBUG
|
||||
JS_FRIEND_API(bool) IsRootingUnnecessaryForContext(JSContext *cx);
|
||||
JS_FRIEND_API(void) SetRootingUnnecessaryForContext(JSContext *cx, bool value);
|
||||
JS_FRIEND_API(bool) RelaxRootChecksForContext(JSContext *cx);
|
||||
#endif
|
||||
|
||||
RootedVar(JSContext *cx, T initial)
|
||||
: ptr(initial), root(cx, &ptr)
|
||||
{}
|
||||
|
||||
operator T () const { return ptr; }
|
||||
T operator ->() const { return ptr; }
|
||||
T * address() { return &ptr; }
|
||||
const T * address() const { return &ptr; }
|
||||
T & reference() { return ptr; }
|
||||
T raw() { return ptr; }
|
||||
|
||||
/*
|
||||
* This method is only necessary due to an obscure C++98 requirement (that
|
||||
* there be an accessible, usable copy constructor when passing a temporary
|
||||
* to an implicitly-called constructor for use with a const-ref parameter).
|
||||
* (Head spinning yet?) We can remove this when we build the JS engine
|
||||
* with -std=c++11.
|
||||
*/
|
||||
operator Handle<T> () const { return Handle<T>(*this); }
|
||||
|
||||
T & operator =(T value)
|
||||
class AssertRootingUnnecessary {
|
||||
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||
JSContext *cx;
|
||||
bool prev;
|
||||
public:
|
||||
AssertRootingUnnecessary(JSContext *cx JS_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
: cx(cx)
|
||||
{
|
||||
JS_ASSERT(!RootMethods<T>::poisoned(value));
|
||||
ptr = value;
|
||||
return ptr;
|
||||
JS_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
#ifdef DEBUG
|
||||
prev = IsRootingUnnecessaryForContext(cx);
|
||||
SetRootingUnnecessaryForContext(cx, true);
|
||||
#endif
|
||||
}
|
||||
|
||||
T & operator =(const RootedVar &value)
|
||||
{
|
||||
ptr = value;
|
||||
return ptr;
|
||||
~AssertRootingUnnecessary() {
|
||||
#ifdef DEBUG
|
||||
SetRootingUnnecessaryForContext(cx, prev);
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
T ptr;
|
||||
Root<T> root;
|
||||
|
||||
RootedVar() MOZ_DELETE;
|
||||
RootedVar(const RootedVar &) MOZ_DELETE;
|
||||
};
|
||||
|
||||
template <typename T> template <typename S>
|
||||
inline
|
||||
Handle<T>::Handle(const RootedVar<S> &root)
|
||||
{
|
||||
testAssign<S>();
|
||||
ptr = reinterpret_cast<const T *>(root.address());
|
||||
}
|
||||
#if defined(DEBUG) && defined(JS_GC_ZEAL) && defined(JSGC_ROOT_ANALYSIS) && !defined(JS_THREADSAFE)
|
||||
extern void
|
||||
CheckStackRoots(JSContext *cx);
|
||||
#endif
|
||||
|
||||
typedef RootedVar<JSObject*> RootedVarObject;
|
||||
typedef RootedVar<JSFunction*> RootedVarFunction;
|
||||
typedef RootedVar<JSString*> RootedVarString;
|
||||
typedef RootedVar<jsid> RootedVarId;
|
||||
typedef RootedVar<Value> RootedVarValue;
|
||||
/*
|
||||
* Hook for dynamic root analysis. Checks the native stack and poisons
|
||||
* references to GC things which have not been rooted.
|
||||
*/
|
||||
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 */
|
||||
|
||||
|
|
|
@ -1,41 +1,9 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sw=4 et tw=78:
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is SpiderMonkey JavaScript engine.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* the Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
* 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 jsgc_statistics_h___
|
||||
#define jsgc_statistics_h___
|
||||
|
@ -56,19 +24,26 @@ enum Phase {
|
|||
PHASE_WAIT_BACKGROUND_THREAD,
|
||||
PHASE_PURGE,
|
||||
PHASE_MARK,
|
||||
PHASE_MARK_DISCARD_CODE,
|
||||
PHASE_MARK_ROOTS,
|
||||
PHASE_MARK_TYPES,
|
||||
PHASE_MARK_DELAYED,
|
||||
PHASE_MARK_OTHER,
|
||||
PHASE_MARK_WEAK,
|
||||
PHASE_MARK_GRAY,
|
||||
PHASE_MARK_GRAY_WEAK,
|
||||
PHASE_FINALIZE_START,
|
||||
PHASE_SWEEP,
|
||||
PHASE_SWEEP_ATOMS,
|
||||
PHASE_SWEEP_COMPARTMENTS,
|
||||
PHASE_SWEEP_TABLES,
|
||||
PHASE_SWEEP_OBJECT,
|
||||
PHASE_SWEEP_STRING,
|
||||
PHASE_SWEEP_SCRIPT,
|
||||
PHASE_SWEEP_SHAPE,
|
||||
PHASE_DISCARD_CODE,
|
||||
PHASE_SWEEP_DISCARD_CODE,
|
||||
PHASE_DISCARD_ANALYSIS,
|
||||
PHASE_DISCARD_TI,
|
||||
PHASE_FREE_TI_ARENA,
|
||||
PHASE_SWEEP_TYPES,
|
||||
PHASE_CLEAR_SCRIPT_ANALYSIS,
|
||||
PHASE_FINALIZE_END,
|
||||
|
@ -116,13 +91,19 @@ struct Statistics {
|
|||
FILE *fp;
|
||||
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 compartmentCount;
|
||||
const char *nonincrementalReason;
|
||||
|
||||
struct SliceData {
|
||||
SliceData(gcreason::Reason reason, int64_t start)
|
||||
: reason(reason), resetReason(NULL), start(start)
|
||||
SliceData(gcreason::Reason reason, int64_t start, size_t startFaults)
|
||||
: reason(reason), resetReason(NULL), start(start), startFaults(startFaults)
|
||||
{
|
||||
PodArrayZero(phaseTimes);
|
||||
}
|
||||
|
@ -130,6 +111,7 @@ struct Statistics {
|
|||
gcreason::Reason reason;
|
||||
const char *resetReason;
|
||||
int64_t start, end;
|
||||
size_t startFaults, endFaults;
|
||||
int64_t phaseTimes[PHASE_LIMIT];
|
||||
|
||||
int64_t duration() const { return end - start; }
|
||||
|
@ -138,7 +120,7 @@ struct Statistics {
|
|||
Vector<SliceData, 8, SystemAllocPolicy> slices;
|
||||
|
||||
/* 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. */
|
||||
int64_t phaseTimes[PHASE_LIMIT];
|
||||
|
|
|
@ -2,42 +2,9 @@
|
|||
/* -*- 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 ***** */
|
||||
* 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 js_config_h___
|
||||
#define js_config_h___
|
||||
|
@ -54,7 +21,7 @@
|
|||
|
||||
/* Define to 1 if SpiderMonkey should support the ability to perform
|
||||
entirely too much GC. */
|
||||
/* #undef JS_GC_ZEAL */
|
||||
#define JS_GC_ZEAL 1
|
||||
|
||||
/* Define to 1 if the <endian.h> header is present and
|
||||
useable. See jscpucfg.h. */
|
||||
|
@ -96,4 +63,7 @@
|
|||
correct. */
|
||||
/* #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___ */
|
||||
|
|
|
@ -1,41 +1,8 @@
|
|||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
* This 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/. */
|
||||
|
||||
/*
|
||||
* 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_UNMATCHED_RIGHT_PAREN, 62, 0, JSEXN_SYNTAXERR, "unmatched ) in regular expression")
|
||||
MSG_DEF(JSMSG_TOO_BIG_TO_ENCODE, 63, 0, JSEXN_INTERNALERR, "data are to big to encode")
|
||||
MSG_DEF(JSMSG_UNUSED64, 64, 0, JSEXN_NONE, "")
|
||||
MSG_DEF(JSMSG_UNUSED65, 65, 0, JSEXN_NONE, "")
|
||||
MSG_DEF(JSMSG_ARG_INDEX_OUT_OF_RANGE, 64, 1, JSEXN_RANGEERR, "argument {0} accesses an index that is out of range")
|
||||
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_UNUSED67, 67, 0, JSEXN_NONE, "")
|
||||
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_XML_NAME_SYNTAX, 173, 0, JSEXN_SYNTAXERR, "invalid XML name")
|
||||
MSG_DEF(JSMSG_BRACKET_AFTER_ATTR_EXPR,174, 0, JSEXN_SYNTAXERR, "missing ] after attribute expression")
|
||||
MSG_DEF(JSMSG_NESTING_GENERATOR, 175, 1, JSEXN_TYPEERR, "already executing generator {0}")
|
||||
MSG_DEF(JSMSG_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_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}")
|
||||
|
@ -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_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_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 -*-
|
||||
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released
|
||||
* 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 ***** */
|
||||
* 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 jshashtable_h_
|
||||
#define jshashtable_h_
|
||||
|
@ -97,7 +62,7 @@ class HashTableEntry {
|
|||
JS_ASSERT(isLive()); keyHash |= collisionBit;
|
||||
}
|
||||
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; }
|
||||
HashNumber getKeyHash() const { JS_ASSERT(!hasCollision()); return keyHash; }
|
||||
};
|
||||
|
@ -177,21 +142,23 @@ class HashTable : private AllocPolicy
|
|||
protected:
|
||||
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())
|
||||
++cur;
|
||||
}
|
||||
|
||||
Entry *cur, *end;
|
||||
DebugOnly<bool> validEntry;
|
||||
|
||||
public:
|
||||
Range() : cur(NULL), end(NULL) {}
|
||||
Range() : cur(NULL), end(NULL), validEntry(false) {}
|
||||
|
||||
bool empty() const {
|
||||
return cur == end;
|
||||
}
|
||||
|
||||
T &front() const {
|
||||
JS_ASSERT(validEntry);
|
||||
JS_ASSERT(!empty());
|
||||
return cur->t;
|
||||
}
|
||||
|
@ -200,6 +167,7 @@ class HashTable : private AllocPolicy
|
|||
JS_ASSERT(!empty());
|
||||
while (++cur < end && !cur->isLive())
|
||||
continue;
|
||||
validEntry = true;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -217,7 +185,7 @@ class HashTable : private AllocPolicy
|
|||
friend class HashTable;
|
||||
|
||||
HashTable &table;
|
||||
bool added;
|
||||
bool rekeyed;
|
||||
bool removed;
|
||||
|
||||
/* Not copyable. */
|
||||
|
@ -226,7 +194,7 @@ class HashTable : private AllocPolicy
|
|||
|
||||
public:
|
||||
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()|
|
||||
|
@ -240,6 +208,7 @@ class HashTable : private AllocPolicy
|
|||
void removeFront() {
|
||||
table.remove(*this->cur);
|
||||
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
|
||||
* 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(!table.match(*this->cur, k));
|
||||
Entry e = *this->cur;
|
||||
HashPolicy::setKey(e.t, k);
|
||||
if (match(*this->cur, l))
|
||||
return;
|
||||
typename HashTableEntry<T>::NonConstT t = this->cur->t;
|
||||
HashPolicy::setKey(t, const_cast<Key &>(k));
|
||||
table.remove(*this->cur);
|
||||
table.add(k, e);
|
||||
added = true;
|
||||
table.putNewInfallible(l, t);
|
||||
rekeyed = true;
|
||||
this->validEntry = false;
|
||||
}
|
||||
|
||||
void rekeyFront(const Key &k) {
|
||||
rekeyFront(k, k);
|
||||
}
|
||||
|
||||
/* Potentially rehashes the table. */
|
||||
~Enum() {
|
||||
if (added)
|
||||
table.checkOverloaded();
|
||||
if (rekeyed)
|
||||
table.checkOverRemoved();
|
||||
if (removed)
|
||||
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:
|
||||
|
@ -301,6 +264,7 @@ class HashTable : private AllocPolicy
|
|||
uint32_t grows; /* table expansions */
|
||||
uint32_t shrinks; /* table contractions */
|
||||
uint32_t compresses; /* table compressions */
|
||||
uint32_t rehashes; /* tombstone decontaminations */
|
||||
} stats;
|
||||
# define METER(x) x
|
||||
#else
|
||||
|
@ -384,7 +348,7 @@ class HashTable : private AllocPolicy
|
|||
mutationCount(0)
|
||||
{}
|
||||
|
||||
bool init(uint32_t length)
|
||||
MOZ_WARN_UNUSED_RESULT bool init(uint32_t length)
|
||||
{
|
||||
/* Make sure that init isn't called twice. */
|
||||
JS_ASSERT(table == NULL);
|
||||
|
@ -533,8 +497,9 @@ class HashTable : private AllocPolicy
|
|||
*/
|
||||
Entry &findFreeEntry(HashNumber keyHash)
|
||||
{
|
||||
METER(stats.searches++);
|
||||
JS_ASSERT(!(keyHash & sCollisionBit));
|
||||
JS_ASSERT(table);
|
||||
METER(stats.searches++);
|
||||
|
||||
/* N.B. the |keyHash| has already been distributed. */
|
||||
|
||||
|
@ -543,7 +508,7 @@ class HashTable : private AllocPolicy
|
|||
Entry *entry = &table[h1];
|
||||
|
||||
/* Miss: return space for a new entry. */
|
||||
if (entry->isFree()) {
|
||||
if (!entry->isLive()) {
|
||||
METER(stats.misses++);
|
||||
return *entry;
|
||||
}
|
||||
|
@ -559,14 +524,16 @@ class HashTable : private AllocPolicy
|
|||
h1 = applyDoubleHash(h1, dh);
|
||||
|
||||
entry = &table[h1];
|
||||
if (entry->isFree()) {
|
||||
if (!entry->isLive()) {
|
||||
METER(stats.misses++);
|
||||
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. */
|
||||
Entry *oldTable = table;
|
||||
|
@ -575,12 +542,12 @@ class HashTable : private AllocPolicy
|
|||
uint32_t newCapacity = JS_BIT(newLog2);
|
||||
if (newCapacity > sMaxCapacity) {
|
||||
this->reportAllocOverflow();
|
||||
return false;
|
||||
return RehashFailed;
|
||||
}
|
||||
|
||||
Entry *newTable = createTable(*this, newCapacity);
|
||||
if (!newTable)
|
||||
return false;
|
||||
return RehashFailed;
|
||||
|
||||
/* We can't fail from here on, so update table parameters. */
|
||||
setTableSizeLog2(newLog2);
|
||||
|
@ -597,30 +564,13 @@ class HashTable : private AllocPolicy
|
|||
}
|
||||
|
||||
destroyTable(*this, oldTable, oldCap);
|
||||
return true;
|
||||
return Rehashed;
|
||||
}
|
||||
|
||||
void add(const Lookup &l, const Entry &e)
|
||||
{
|
||||
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()
|
||||
RebuildStatus checkOverloaded()
|
||||
{
|
||||
if (!overloaded())
|
||||
return false;
|
||||
return NotOverloaded;
|
||||
|
||||
/* Compress if a quarter or more of all entries are removed. */
|
||||
int deltaLog2;
|
||||
|
@ -635,9 +585,21 @@ class HashTable : private AllocPolicy
|
|||
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)
|
||||
{
|
||||
JS_ASSERT(table);
|
||||
METER(stats.removes++);
|
||||
|
||||
if (e.hasCollision()) {
|
||||
e.setRemoved();
|
||||
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:
|
||||
void clear()
|
||||
{
|
||||
|
@ -688,22 +696,27 @@ class HashTable : private AllocPolicy
|
|||
}
|
||||
|
||||
Range all() const {
|
||||
JS_ASSERT(table);
|
||||
return Range(table, table + capacity());
|
||||
}
|
||||
|
||||
bool empty() const {
|
||||
JS_ASSERT(table);
|
||||
return !entryCount;
|
||||
}
|
||||
|
||||
uint32_t count() const {
|
||||
JS_ASSERT(table);
|
||||
return entryCount;
|
||||
}
|
||||
|
||||
uint32_t capacity() const {
|
||||
JS_ASSERT(table);
|
||||
return JS_BIT(sHashBits - hashShift);
|
||||
}
|
||||
|
||||
uint32_t generation() const {
|
||||
JS_ASSERT(table);
|
||||
return gen;
|
||||
}
|
||||
|
||||
|
@ -747,8 +760,11 @@ class HashTable : private AllocPolicy
|
|||
removedCount--;
|
||||
p.keyHash |= sCollisionBit;
|
||||
} 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);
|
||||
}
|
||||
|
||||
|
@ -779,6 +795,34 @@ class HashTable : private AllocPolicy
|
|||
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)
|
||||
{
|
||||
p.mutationCount = mutationCount;
|
||||
|
@ -791,6 +835,7 @@ class HashTable : private AllocPolicy
|
|||
|
||||
void remove(Ptr p)
|
||||
{
|
||||
JS_ASSERT(table);
|
||||
ReentrancyGuard g(*this);
|
||||
JS_ASSERT(p.found());
|
||||
remove(*p.entry);
|
||||
|
@ -1163,9 +1208,7 @@ class HashMap
|
|||
|
||||
/* Like put, but assert that the given key is not already present. */
|
||||
bool putNew(const Key &k, const Value &v) {
|
||||
AddPtr p = lookupForAdd(k);
|
||||
JS_ASSERT(!p);
|
||||
return add(p, k, v);
|
||||
return impl.putNew(k, Entry(k, v));
|
||||
}
|
||||
|
||||
/* 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. */
|
||||
bool putNew(const T &t) {
|
||||
AddPtr p = lookupForAdd(t);
|
||||
JS_ASSERT(!p);
|
||||
return add(p, t);
|
||||
return impl.putNew(t, t);
|
||||
}
|
||||
|
||||
bool putNew(const Lookup &l, const T &t) {
|
||||
AddPtr p = lookupForAdd(l);
|
||||
JS_ASSERT(!p);
|
||||
return add(p, t);
|
||||
return impl.putNew(l, t);
|
||||
}
|
||||
|
||||
void remove(const Lookup &l) {
|
||||
|
|
|
@ -1,40 +1,7 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/* This 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/. */
|
||||
|
||||
/*
|
||||
* 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 -*-
|
||||
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is about:memory glue.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Ms2ger <ms2ger@gmail.com>.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
* 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 js_MemoryMetrics_h
|
||||
#define js_MemoryMetrics_h
|
||||
|
@ -62,6 +30,53 @@ struct TypeInferenceSizes
|
|||
size_t objects;
|
||||
size_t tables;
|
||||
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
|
||||
|
@ -70,10 +85,14 @@ struct CompartmentStats
|
|||
memset(this, 0, sizeof(*this));
|
||||
}
|
||||
|
||||
void *extra;
|
||||
size_t gcHeapArenaHeaders;
|
||||
size_t gcHeapArenaPadding;
|
||||
size_t gcHeapArenaUnused;
|
||||
// These fields can be used by embedders.
|
||||
void *extra1;
|
||||
void *extra2;
|
||||
|
||||
// If you add a new number, remember to update add() and maybe
|
||||
// gcHeapThingsSize()!
|
||||
size_t gcHeapArenaAdmin;
|
||||
size_t gcHeapUnusedGcThings;
|
||||
|
||||
size_t gcHeapObjectsNonFunction;
|
||||
size_t gcHeapObjectsFunction;
|
||||
|
@ -83,83 +102,116 @@ struct CompartmentStats
|
|||
size_t gcHeapShapesBase;
|
||||
size_t gcHeapScripts;
|
||||
size_t gcHeapTypeObjects;
|
||||
#if JS_HAS_XML_SUPPORT
|
||||
size_t gcHeapXML;
|
||||
#endif
|
||||
|
||||
size_t objectSlots;
|
||||
size_t objectElements;
|
||||
size_t objectMisc;
|
||||
size_t objectPrivate;
|
||||
size_t stringChars;
|
||||
size_t shapesExtraTreeTables;
|
||||
size_t shapesExtraDictTables;
|
||||
size_t shapesExtraTreeShapeKids;
|
||||
size_t shapesCompartmentTables;
|
||||
size_t scriptData;
|
||||
|
||||
#ifdef JS_METHODJIT
|
||||
size_t mjitCode;
|
||||
size_t mjitData;
|
||||
#endif
|
||||
size_t crossCompartmentWrappers;
|
||||
|
||||
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
|
||||
{
|
||||
RuntimeStats(JSMallocSizeOfFun mallocSizeOf)
|
||||
: runtimeObject(0)
|
||||
, runtimeAtomsTable(0)
|
||||
, runtimeContexts(0)
|
||||
, runtimeNormal(0)
|
||||
, runtimeTemporary(0)
|
||||
, runtimeRegexpCode(0)
|
||||
, runtimeStackCommitted(0)
|
||||
, runtimeGCMarker(0)
|
||||
: runtime()
|
||||
, gcHeapChunkTotal(0)
|
||||
, gcHeapChunkCleanUnused(0)
|
||||
, gcHeapChunkDirtyUnused(0)
|
||||
, gcHeapChunkCleanDecommitted(0)
|
||||
, gcHeapChunkDirtyDecommitted(0)
|
||||
, gcHeapArenaUnused(0)
|
||||
, gcHeapDecommittedArenas(0)
|
||||
, gcHeapUnusedChunks(0)
|
||||
, gcHeapUnusedArenas(0)
|
||||
, gcHeapUnusedGcThings(0)
|
||||
, gcHeapChunkAdmin(0)
|
||||
, gcHeapUnusedPercentage(0)
|
||||
, totalObjects(0)
|
||||
, totalShapes(0)
|
||||
, totalScripts(0)
|
||||
, totalStrings(0)
|
||||
#ifdef JS_METHODJIT
|
||||
, totalMjit(0)
|
||||
#endif
|
||||
, totalTypeInference(0)
|
||||
, totalAnalysisTemp(0)
|
||||
, gcHeapGcThings(0)
|
||||
, totals()
|
||||
, compartmentStatsVector()
|
||||
, currCompartmentStats(NULL)
|
||||
, mallocSizeOf(mallocSizeOf)
|
||||
{}
|
||||
|
||||
size_t runtimeObject;
|
||||
size_t runtimeAtomsTable;
|
||||
size_t runtimeContexts;
|
||||
size_t runtimeNormal;
|
||||
size_t runtimeTemporary;
|
||||
size_t runtimeRegexpCode;
|
||||
size_t runtimeStackCommitted;
|
||||
size_t runtimeGCMarker;
|
||||
RuntimeSizes runtime;
|
||||
|
||||
// If you add a new number, remember to update the constructor!
|
||||
|
||||
// Here's a useful breakdown of the GC heap.
|
||||
//
|
||||
// - rtStats.gcHeapChunkTotal
|
||||
// - 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 gcHeapChunkCleanUnused;
|
||||
size_t gcHeapChunkDirtyUnused;
|
||||
size_t gcHeapChunkCleanDecommitted;
|
||||
size_t gcHeapChunkDirtyDecommitted;
|
||||
size_t gcHeapArenaUnused;
|
||||
size_t gcHeapDecommittedArenas;
|
||||
size_t gcHeapUnusedChunks;
|
||||
size_t gcHeapUnusedArenas;
|
||||
size_t gcHeapUnusedGcThings;
|
||||
size_t gcHeapChunkAdmin;
|
||||
size_t gcHeapUnusedPercentage;
|
||||
size_t totalObjects;
|
||||
size_t totalShapes;
|
||||
size_t totalScripts;
|
||||
size_t totalStrings;
|
||||
#ifdef JS_METHODJIT
|
||||
size_t totalMjit;
|
||||
#endif
|
||||
size_t totalTypeInference;
|
||||
size_t totalAnalysisTemp;
|
||||
size_t gcHeapGcThings;
|
||||
|
||||
// The sum of all compartment's measurements.
|
||||
CompartmentStats totals;
|
||||
|
||||
js::Vector<CompartmentStats, 0, js::SystemAllocPolicy> compartmentStatsVector;
|
||||
CompartmentStats *currCompartmentStats;
|
||||
|
@ -171,8 +223,16 @@ struct RuntimeStats
|
|||
|
||||
#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)
|
||||
CollectRuntimeStats(JSRuntime *rt, RuntimeStats *rtStats);
|
||||
CollectRuntimeStats(JSRuntime *rt, RuntimeStats *rtStats, ObjectPrivateVisitor *opv);
|
||||
|
||||
extern JS_PUBLIC_API(int64_t)
|
||||
GetExplicitNonHeapForRuntime(JSRuntime *rt, JSMallocSizeOfFun mallocSizeOf);
|
||||
|
|
|
@ -1,42 +1,9 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla SpiderMonkey JavaScript code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* the Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Luke Wagner <luke@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
* 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 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 <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.
|
||||
*/
|
||||
template <class T> struct IsPostBarrieredType { static const bool result = false; };
|
||||
template <class T> struct IsRelocatableHeapType { static const bool result = true; };
|
||||
|
||||
} /* namespace tl */
|
||||
} /* namespace js */
|
||||
|
|
|
@ -1,46 +1,15 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla SpiderMonkey JavaScript code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* the Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* 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 ***** */
|
||||
* 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 js_utility_h__
|
||||
#define js_utility_h__
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
@ -53,6 +22,7 @@
|
|||
#include "jstypes.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
# include "mozilla/Scoped.h"
|
||||
|
||||
/* The public JS engine namespace. */
|
||||
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_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,
|
||||
* call to the debugger or other moral equivalent as well as causing the
|
||||
|
@ -626,6 +599,15 @@ public:
|
|||
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 */
|
||||
|
||||
/*
|
||||
|
@ -847,7 +829,7 @@ class MoveRef {
|
|||
explicit MoveRef(T &t) : pointer(&t) { }
|
||||
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
|
||||
* 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 -*-
|
||||
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released
|
||||
* 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 ***** */
|
||||
* 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 jsvector_h_
|
||||
#define jsvector_h_
|
||||
|
@ -213,7 +180,7 @@ struct VectorImpl<T, N, AP, true>
|
|||
template <class T, size_t N, class AllocPolicy>
|
||||
class Vector : private AllocPolicy
|
||||
{
|
||||
typedef typename tl::StaticAssert<!tl::IsPostBarrieredType<T>::result>::result _;
|
||||
typedef typename tl::StaticAssert<tl::IsRelocatableHeapType<T>::result>::result _;
|
||||
|
||||
/* utilities */
|
||||
|
||||
|
@ -596,7 +563,12 @@ Vector<T,N,AP>::~Vector()
|
|||
*/
|
||||
template <class T, size_t N, class AP>
|
||||
STATIC_POSTCONDITION(!return || newCap >= curLength + lengthInc)
|
||||
#ifdef DEBUG
|
||||
/* gcc (ARM, x86) compiler bug workaround - See bug 694694 */
|
||||
JS_NEVER_INLINE bool
|
||||
#else
|
||||
inline bool
|
||||
#endif
|
||||
Vector<T,N,AP>::calculateNewCapacity(size_t curLength, size_t lengthInc,
|
||||
size_t &newCap)
|
||||
{
|
||||
|
|
|
@ -1,40 +1,9 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released
|
||||
* July 16, 2009.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* the Mozilla Corporation.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
* 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 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 -*-
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
* This 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 jsatom_h___
|
||||
#define jsatom_h___
|
||||
|
@ -67,14 +34,37 @@ JSID_FROM_BITS(size_t bits)
|
|||
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
|
||||
ATOM_TO_JSID(JSAtom *atom)
|
||||
NON_INTEGER_ATOM_TO_JSID(JSAtom *atom)
|
||||
{
|
||||
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
|
||||
JSID_IS_ATOM(jsid id)
|
||||
{
|
||||
|
@ -84,7 +74,7 @@ JSID_IS_ATOM(jsid id)
|
|||
static JS_ALWAYS_INLINE JSBool
|
||||
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 *
|
||||
|
@ -93,9 +83,6 @@ JSID_TO_ATOM(jsid id)
|
|||
return (JSAtom *)JSID_TO_STRING(id);
|
||||
}
|
||||
|
||||
extern jsid
|
||||
js_CheckForStringIndex(jsid id);
|
||||
|
||||
JS_STATIC_ASSERT(sizeof(JSHashNumber) == 4);
|
||||
JS_STATIC_ASSERT(sizeof(jsid) == JS_BYTES_PER_WORD);
|
||||
|
||||
|
@ -104,7 +91,6 @@ namespace js {
|
|||
static JS_ALWAYS_INLINE JSHashNumber
|
||||
HashId(jsid id)
|
||||
{
|
||||
JS_ASSERT(js_CheckForStringIndex(id) == id);
|
||||
JSHashNumber n =
|
||||
#if JS_BYTES_PER_WORD == 4
|
||||
JSHashNumber(JSID_BITS(id));
|
||||
|
@ -140,11 +126,9 @@ struct DefaultHasher<jsid>
|
|||
{
|
||||
typedef jsid Lookup;
|
||||
static HashNumber hash(const Lookup &l) {
|
||||
JS_ASSERT(l == js_CheckForStringIndex(l));
|
||||
return HashNumber(JSID_BITS(l));
|
||||
}
|
||||
static bool match(const jsid &id, const Lookup &l) {
|
||||
JS_ASSERT(l == js_CheckForStringIndex(l));
|
||||
return id == l;
|
||||
}
|
||||
};
|
||||
|
@ -291,38 +275,7 @@ struct JSAtomState
|
|||
#undef DEFINE_PROTOTYPE_ATOM
|
||||
#undef DEFINE_KEYWORD_ATOM
|
||||
|
||||
/* Less frequently used atoms, pinned lazily by JS_ResolveStandardClass. */
|
||||
struct {
|
||||
js::PropertyName *XMLListAtom;
|
||||
js::PropertyName *decodeURIAtom;
|
||||
js::PropertyName *decodeURIComponentAtom;
|
||||
js::PropertyName *defineGetterAtom;
|
||||
js::PropertyName *defineSetterAtom;
|
||||
js::PropertyName *encodeURIAtom;
|
||||
js::PropertyName *encodeURIComponentAtom;
|
||||
js::PropertyName *escapeAtom;
|
||||
js::PropertyName *hasOwnPropertyAtom;
|
||||
js::PropertyName *isFiniteAtom;
|
||||
js::PropertyName *isNaNAtom;
|
||||
js::PropertyName *isPrototypeOfAtom;
|
||||
js::PropertyName *isXMLNameAtom;
|
||||
js::PropertyName *lookupGetterAtom;
|
||||
js::PropertyName *lookupSetterAtom;
|
||||
js::PropertyName *parseFloatAtom;
|
||||
js::PropertyName *parseIntAtom;
|
||||
js::PropertyName *propertyIsEnumerableAtom;
|
||||
js::PropertyName *unescapeAtom;
|
||||
js::PropertyName *unevalAtom;
|
||||
js::PropertyName *unwatchAtom;
|
||||
js::PropertyName *watchAtom;
|
||||
} lazy;
|
||||
|
||||
static const size_t commonAtomsOffset;
|
||||
static const size_t lazyAtomsOffset;
|
||||
|
||||
void clearLazyAtoms() {
|
||||
memset(&lazy, 0, sizeof(lazy));
|
||||
}
|
||||
|
||||
void junkAtoms() {
|
||||
#ifdef DEBUG
|
||||
|
@ -340,7 +293,7 @@ struct JSAtomState
|
|||
extern bool
|
||||
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) \
|
||||
((offsetof(JSAtomState, name##Atom) - JSAtomState::commonAtomsOffset) \
|
||||
|
@ -349,10 +302,10 @@ AtomIsInterned(JSContext *cx, JSAtom *atom);
|
|||
((offsetof(JSAtomState, typeAtoms[type]) - JSAtomState::commonAtomsOffset)\
|
||||
/ sizeof(JSAtom*))
|
||||
|
||||
#define ATOM_OFFSET(name) offsetof(JSAtomState, name##Atom)
|
||||
#define OFFSET_TO_ATOM(rt,off) (*(JSAtom **)((char*)&(rt)->atomState + (off)))
|
||||
#define CLASS_ATOM_OFFSET(name) offsetof(JSAtomState, classAtoms[JSProto_##name])
|
||||
#define CLASS_ATOM(cx,name) ((cx)->runtime->atomState.classAtoms[JSProto_##name])
|
||||
#define NAME_OFFSET(name) offsetof(JSAtomState, name##Atom)
|
||||
#define OFFSET_TO_NAME(rt,off) (*(js::PropertyName **)((char*)&(rt)->atomState + (off)))
|
||||
#define CLASS_NAME_OFFSET(name) offsetof(JSAtomState, classAtoms[JSProto_##name])
|
||||
#define CLASS_NAME(cx,name) ((cx)->runtime->atomState.classAtoms[JSProto_##name])
|
||||
|
||||
extern const char *const js_common_atom_names[];
|
||||
extern const size_t js_common_atom_count;
|
||||
|
@ -457,28 +410,29 @@ js_DumpAtoms(JSContext *cx, FILE *fp);
|
|||
|
||||
#endif
|
||||
|
||||
inline bool
|
||||
js_ValueToAtom(JSContext *cx, const js::Value &v, JSAtom **atomp);
|
||||
|
||||
inline bool
|
||||
js_ValueToStringId(JSContext *cx, const js::Value &v, jsid *idp);
|
||||
|
||||
inline bool
|
||||
js_InternNonIntElementId(JSContext *cx, JSObject *obj, const js::Value &idval,
|
||||
jsid *idp);
|
||||
inline bool
|
||||
js_InternNonIntElementId(JSContext *cx, JSObject *obj, const js::Value &idval,
|
||||
jsid *idp, js::Value *vp);
|
||||
|
||||
namespace js {
|
||||
|
||||
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
|
||||
* to its address. map->length must already be set to the number of atoms in
|
||||
* the list and map->vector must point to pre-allocated memory.
|
||||
*/
|
||||
extern void
|
||||
InitAtomMap(JSContext *cx, AtomIndexMap *indices, HeapPtrAtom *atoms);
|
||||
InitAtomMap(JSContext *cx, AtomIndexMap *indices, HeapPtr<JSAtom> *atoms);
|
||||
|
||||
template<XDRMode mode>
|
||||
bool
|
||||
|
|
|
@ -118,8 +118,33 @@ DEFINE_ATOM(hasOwn, "hasOwn")
|
|||
DEFINE_ATOM(keys, "keys")
|
||||
DEFINE_ATOM(iterate, "iterate")
|
||||
DEFINE_PROTOTYPE_ATOM(WeakMap)
|
||||
DEFINE_ATOM(buffer, "buffer")
|
||||
DEFINE_ATOM(byteLength, "byteLength")
|
||||
DEFINE_ATOM(byteOffset, "byteOffset")
|
||||
DEFINE_KEYWORD_ATOM(return)
|
||||
DEFINE_KEYWORD_ATOM(throw)
|
||||
DEFINE_ATOM(url, "url")
|
||||
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 -*-
|
||||
* vim: set ts=4 sw=4 et tw=79 ft=cpp:
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is SpiderMonkey JavaScript engine.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2009
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
* 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 jsclass_h__
|
||||
#define jsclass_h__
|
||||
|
@ -54,6 +22,7 @@ namespace js {
|
|||
|
||||
class PropertyName;
|
||||
class SpecialId;
|
||||
class PropertyId;
|
||||
|
||||
static JS_ALWAYS_INLINE jsid
|
||||
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
|
||||
* valid identifier; or JS_DEFAULT_XML_NAMESPACE_ID, if E4X is enabled.
|
||||
*/
|
||||
|
||||
class SpecialId {
|
||||
class SpecialId
|
||||
{
|
||||
uintptr_t bits;
|
||||
|
||||
/* Needs access to raw bits. */
|
||||
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_OBJECT = JSID_TYPE_OBJECT;
|
||||
|
@ -174,83 +144,75 @@ JSID_TO_SPECIALID(jsid id)
|
|||
return SpecialId::defaultXMLNamespace();
|
||||
}
|
||||
|
||||
typedef JS::Handle<SpecialId> HandleSpecialId;
|
||||
|
||||
/* js::Class operation signatures. */
|
||||
|
||||
typedef JSBool
|
||||
(* LookupGenericOp)(JSContext *cx, JSObject *obj, jsid id, JSObject **objp,
|
||||
JSProperty **propp);
|
||||
(* LookupGenericOp)(JSContext *cx, HandleObject obj, HandleId id,
|
||||
MutableHandleObject objp, MutableHandleShape propp);
|
||||
typedef JSBool
|
||||
(* LookupPropOp)(JSContext *cx, JSObject *obj, PropertyName *name, JSObject **objp,
|
||||
JSProperty **propp);
|
||||
(* LookupPropOp)(JSContext *cx, HandleObject obj, HandlePropertyName name,
|
||||
MutableHandleObject objp, MutableHandleShape propp);
|
||||
typedef JSBool
|
||||
(* LookupElementOp)(JSContext *cx, JSObject *obj, uint32_t index, JSObject **objp,
|
||||
JSProperty **propp);
|
||||
(* LookupElementOp)(JSContext *cx, HandleObject obj, uint32_t index,
|
||||
MutableHandleObject objp, MutableHandleShape propp);
|
||||
typedef JSBool
|
||||
(* LookupSpecialOp)(JSContext *cx, JSObject *obj, SpecialId sid, JSObject **objp,
|
||||
JSProperty **propp);
|
||||
(* LookupSpecialOp)(JSContext *cx, HandleObject obj, HandleSpecialId sid,
|
||||
MutableHandleObject objp, MutableHandleShape propp);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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
|
||||
(* PropertyIdOp)(JSContext *cx, JSObject *obj, JSObject *receiver, PropertyName *name, Value *vp);
|
||||
(* PropertyIdOp)(JSContext *cx, HandleObject obj, HandleObject receiver, HandlePropertyName name, Value *vp);
|
||||
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
|
||||
(* 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
|
||||
(* SpecialIdOp)(JSContext *cx, JSObject *obj, JSObject *receiver, SpecialId sid, Value *vp);
|
||||
(* SpecialIdOp)(JSContext *cx, HandleObject obj, HandleObject receiver, HandleSpecialId sid, Value *vp);
|
||||
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
|
||||
(* StrictPropertyIdOp)(JSContext *cx, JSObject *obj, PropertyName *name, Value *vp, JSBool strict);
|
||||
(* StrictPropertyIdOp)(JSContext *cx, HandleObject obj, HandlePropertyName name, Value *vp, JSBool strict);
|
||||
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
|
||||
(* StrictSpecialIdOp)(JSContext *cx, JSObject *obj, SpecialId sid, Value *vp, JSBool strict);
|
||||
(* StrictSpecialIdOp)(JSContext *cx, HandleObject obj, HandleSpecialId sid, Value *vp, JSBool strict);
|
||||
typedef JSBool
|
||||
(* GenericAttributesOp)(JSContext *cx, JSObject *obj, jsid id, unsigned *attrsp);
|
||||
(* GenericAttributesOp)(JSContext *cx, HandleObject obj, HandleId id, unsigned *attrsp);
|
||||
typedef JSBool
|
||||
(* PropertyAttributesOp)(JSContext *cx, JSObject *obj, PropertyName *name, unsigned *attrsp);
|
||||
(* PropertyAttributesOp)(JSContext *cx, HandleObject obj, HandlePropertyName name, unsigned *attrsp);
|
||||
typedef JSBool
|
||||
(* ElementAttributesOp)(JSContext *cx, JSObject *obj, uint32_t index, unsigned *attrsp);
|
||||
(* ElementAttributesOp)(JSContext *cx, HandleObject obj, uint32_t index, unsigned *attrsp);
|
||||
typedef JSBool
|
||||
(* SpecialAttributesOp)(JSContext *cx, JSObject *obj, SpecialId sid, unsigned *attrsp);
|
||||
(* SpecialAttributesOp)(JSContext *cx, HandleObject obj, HandleSpecialId sid, unsigned *attrsp);
|
||||
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
|
||||
(* 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
|
||||
(* DeleteSpecialOp)(JSContext *cx, JSObject *obj, SpecialId sid, Value *vp, JSBool strict);
|
||||
(* DeleteSpecialOp)(JSContext *cx, HandleObject obj, HandleSpecialId sid, Value *vp, JSBool strict);
|
||||
typedef JSType
|
||||
(* TypeOfOp)(JSContext *cx, JSObject *obj);
|
||||
|
||||
/*
|
||||
* Prepare to make |obj| non-extensible; in particular, fully resolve its properties.
|
||||
* On error, return false.
|
||||
* If |obj| is now ready to become non-extensible, set |*fixed| to true and return true.
|
||||
* If |obj| refuses to become non-extensible, set |*fixed| to false and return true; the
|
||||
* caller will throw an appropriate error.
|
||||
*/
|
||||
typedef JSBool
|
||||
(* FixOp)(JSContext *cx, JSObject *obj, bool *fixed, AutoIdVector *props);
|
||||
(* TypeOfOp)(JSContext *cx, HandleObject obj);
|
||||
|
||||
typedef JSObject *
|
||||
(* ObjectOp)(JSContext *cx, JSObject *obj);
|
||||
(* ObjectOp)(JSContext *cx, HandleObject obj);
|
||||
typedef void
|
||||
(* ClearOp)(JSContext *cx, HandleObject obj);
|
||||
typedef void
|
||||
(* FinalizeOp)(FreeOp *fop, JSObject *obj);
|
||||
typedef void
|
||||
(* ClearOp)(JSContext *cx, JSObject *obj);
|
||||
|
||||
#define JS_CLASS_MEMBERS \
|
||||
const char *name; \
|
||||
|
@ -269,8 +231,8 @@ typedef void
|
|||
/* Optionally non-null members start here. */ \
|
||||
JSCheckAccessOp checkAccess; \
|
||||
JSNative call; \
|
||||
JSNative construct; \
|
||||
JSHasInstanceOp hasInstance; \
|
||||
JSNative construct; \
|
||||
JSTraceOp trace
|
||||
|
||||
/*
|
||||
|
@ -332,7 +294,6 @@ struct ObjectOps
|
|||
|
||||
JSNewEnumerateOp enumerate;
|
||||
TypeOfOp typeOf;
|
||||
FixOp fix;
|
||||
ObjectOp thisObject;
|
||||
ClearOp clear;
|
||||
};
|
||||
|
@ -340,7 +301,7 @@ struct ObjectOps
|
|||
#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}
|
||||
|
||||
struct Class
|
||||
{
|
||||
|
@ -406,7 +367,8 @@ Valueify(const JSClass *c)
|
|||
* value of objects.
|
||||
*/
|
||||
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 {
|
||||
|
||||
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 /* jsclass_h__ */
|
||||
|
|
|
@ -1,40 +1,7 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/* This 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 jsclist_h___
|
||||
#define jsclist_h___
|
||||
|
|
|
@ -1,41 +1,8 @@
|
|||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
* This 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 js_cpucfg___
|
||||
#define js_cpucfg___
|
||||
|
|
|
@ -1,43 +1,9 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sw=4 et tw=99:
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Nick Fitzgerald <nfitzgerald@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
* 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 jsdbgapi_h___
|
||||
#define jsdbgapi_h___
|
||||
|
@ -120,6 +86,13 @@ JS_SetRuntimeDebugMode(JSRuntime *rt, JSBool debug);
|
|||
extern JS_PUBLIC_API(JSBool)
|
||||
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
|
||||
* 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)
|
||||
JS_SetFrameAnnotation(JSContext *cx, JSStackFrame *fp, void *annotation);
|
||||
|
||||
extern JS_PUBLIC_API(JSPrincipals*)
|
||||
JS_GetPrincipalIfDummyFrame(JSContext *cx, JSStackFrame *fpArg);
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
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 *)
|
||||
JS_GetScriptFilename(JSContext *cx, JSScript *script);
|
||||
|
||||
|
@ -352,7 +339,6 @@ typedef struct JSPropertyDesc {
|
|||
jsval value; /* property value */
|
||||
uint8_t flags; /* flags, see below */
|
||||
uint8_t spare; /* unused */
|
||||
uint16_t slot; /* argument/variable slot */
|
||||
jsval alias; /* alias id if JSPD_ALIAS flag */
|
||||
} JSPropertyDesc;
|
||||
|
||||
|
@ -360,8 +346,6 @@ typedef struct JSPropertyDesc {
|
|||
#define JSPD_READONLY 0x02 /* assignment is error */
|
||||
#define JSPD_PERMANENT 0x04 /* property cannot be deleted */
|
||||
#define JSPD_ALIAS 0x08 /* property has an alias id */
|
||||
#define JSPD_ARGUMENT 0x10 /* argument to function */
|
||||
#define JSPD_VARIABLE 0x20 /* local variable in function */
|
||||
#define JSPD_EXCEPTION 0x40 /* exception occurred fetching the property, */
|
||||
/* value is exception */
|
||||
#define JSPD_ERROR 0x80 /* native getter returned JS_FALSE without */
|
||||
|
@ -374,13 +358,6 @@ typedef struct JSPropertyDescArray {
|
|||
|
||||
typedef struct JSScopeProperty JSScopeProperty;
|
||||
|
||||
extern JS_PUBLIC_API(JSScopeProperty *)
|
||||
JS_PropertyIterator(JSObject *obj, JSScopeProperty **iteratorp);
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_GetPropertyDesc(JSContext *cx, JSObject *obj, JSScopeProperty *shape,
|
||||
JSPropertyDesc *pd);
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_GetPropertyDescArray(JSContext *cx, JSObject *obj, JSPropertyDescArray *pda);
|
||||
|
||||
|
@ -418,23 +395,6 @@ JS_GetFunctionTotalSize(JSContext *cx, JSFunction *fun);
|
|||
extern JS_PUBLIC_API(size_t)
|
||||
JS_GetScriptTotalSize(JSContext *cx, JSScript *script);
|
||||
|
||||
/*
|
||||
* Return true if obj is a "system" object, that is, one created by
|
||||
* JS_NewSystemObject with the system flag set and not JS_NewObject.
|
||||
*
|
||||
* What "system" means is up to the API client.
|
||||
*/
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_IsSystemObject(JSContext *cx, JSObject *obj);
|
||||
|
||||
/*
|
||||
* Mark an object as being a system object. This should be called immediately
|
||||
* after allocating the object. A system object is an object for which
|
||||
* JS_IsSystemObject returns true.
|
||||
*/
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_MakeSystemObject(JSContext *cx, JSObject *obj);
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
extern JS_FRIEND_API(void)
|
||||
|
@ -532,6 +492,16 @@ js_ResumeVtune();
|
|||
|
||||
#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)
|
||||
JS_DumpBytecode(JSContext *cx, JSScript *script);
|
||||
|
||||
|
@ -547,6 +517,9 @@ JS_DumpCompartmentPCCounts(JSContext *cx);
|
|||
extern JS_PUBLIC_API(JSObject *)
|
||||
JS_UnwrapObject(JSObject *obj);
|
||||
|
||||
extern JS_PUBLIC_API(JSObject *)
|
||||
JS_UnwrapObjectAndInnerize(JSObject *obj);
|
||||
|
||||
/* Call the context debug handler on the topmost scripted frame. */
|
||||
extern JS_FRIEND_API(JSBool)
|
||||
js_CallContextDebugHandler(JSContext *cx);
|
||||
|
|
|
@ -1,40 +1,7 @@
|
|||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla JavaScript code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1999-2001
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Brendan Eich <brendan@mozilla.org> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/* 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 jsdhash_h___
|
||||
#define jsdhash_h___
|
||||
|
|
|
@ -1,41 +1,8 @@
|
|||
/* -*- 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):
|
||||
*
|
||||
* 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 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 jsfriendapi_h___
|
||||
#define jsfriendapi_h___
|
||||
|
@ -87,6 +54,15 @@ JS_GetCustomIteratorCount(JSContext *cx);
|
|||
extern JS_FRIEND_API(JSBool)
|
||||
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
|
||||
* 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 *)
|
||||
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. */
|
||||
extern JS_FRIEND_API(JSObject *)
|
||||
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);
|
||||
|
||||
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_ReportOverRecursed(JSContext *maybecx);
|
||||
|
@ -164,7 +143,10 @@ extern JS_FRIEND_API(JSBool)
|
|||
JS_WrapPropertyDescriptor(JSContext *cx, js::PropertyDescriptor *desc);
|
||||
|
||||
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 {
|
||||
const char *name;
|
||||
|
@ -217,26 +199,13 @@ GetRuntime(const JSContext *cx)
|
|||
typedef bool
|
||||
(* 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.
|
||||
*/
|
||||
extern JS_FRIEND_API(void)
|
||||
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) {
|
||||
private:
|
||||
JSContext *cx;
|
||||
|
@ -296,6 +265,15 @@ TraceWeakMaps(WeakMapTracer *trc);
|
|||
extern JS_FRIEND_API(bool)
|
||||
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
|
||||
* functions below. Do not use these structures in any other way. When adding
|
||||
|
@ -388,6 +366,9 @@ GetObjectParentMaybeScope(JSObject *obj);
|
|||
JS_FRIEND_API(JSObject *)
|
||||
GetGlobalForObjectCrossCompartment(JSObject *obj);
|
||||
|
||||
JS_FRIEND_API(void)
|
||||
NotifyAnimationActivity(JSObject *obj);
|
||||
|
||||
JS_FRIEND_API(bool)
|
||||
IsOriginalScriptFunction(JSFunction *fun);
|
||||
|
||||
|
@ -498,6 +479,9 @@ CastAsJSStrictPropertyOp(JSObject *object)
|
|||
JS_FRIEND_API(bool)
|
||||
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)
|
||||
StringIsArrayIndex(JSLinearString *str, uint32_t *indexp);
|
||||
|
||||
|
@ -552,6 +536,34 @@ GetPCCountScriptSummary(JSContext *cx, size_t script);
|
|||
JS_FRIEND_API(JSString *)
|
||||
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
|
||||
JS_FRIEND_API(void *)
|
||||
GetOwnerThread(const JSContext *cx);
|
||||
|
@ -581,7 +593,7 @@ extern JS_FRIEND_API(const JSStructuredCloneCallbacks *)
|
|||
GetContextStructuredCloneCallbacks(JSContext *cx);
|
||||
|
||||
extern JS_FRIEND_API(JSVersion)
|
||||
VersionSetXML(JSVersion version, bool enable);
|
||||
VersionSetMoarXML(JSVersion version, bool enable);
|
||||
|
||||
extern JS_FRIEND_API(bool)
|
||||
CanCallContextDebugHandler(JSContext *cx);
|
||||
|
@ -610,8 +622,8 @@ SizeOfJSContext();
|
|||
D(TOO_MUCH_MALLOC) \
|
||||
D(ALLOC_TRIGGER) \
|
||||
D(DEBUG_GC) \
|
||||
D(UNUSED2) /* was SHAPE */ \
|
||||
D(UNUSED3) /* was REFILL */ \
|
||||
D(DEBUG_MODE_GC) \
|
||||
D(TRANSPLANT) \
|
||||
\
|
||||
/* Reasons from Firefox */ \
|
||||
D(DOM_WINDOW_UTILS) \
|
||||
|
@ -629,7 +641,9 @@ SizeOfJSContext();
|
|||
D(DOM_IPC) \
|
||||
D(DOM_WORKER) \
|
||||
D(INTER_SLICE_GC) \
|
||||
D(REFRESH_FRAME)
|
||||
D(REFRESH_FRAME) \
|
||||
D(FULL_GC_TIMER) \
|
||||
D(SHUTDOWN_CC)
|
||||
|
||||
namespace gcreason {
|
||||
|
||||
|
@ -639,7 +653,15 @@ enum Reason {
|
|||
GCREASONS(MAKE_REASON)
|
||||
#undef MAKE_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 */
|
||||
|
@ -650,6 +672,15 @@ PrepareCompartmentForGC(JSCompartment *comp);
|
|||
extern JS_FRIEND_API(void)
|
||||
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
|
||||
* 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);
|
||||
|
||||
extern JS_FRIEND_API(void)
|
||||
SetGCSliceTimeBudget(JSContext *cx, int64_t millis);
|
||||
FinishIncrementalGC(JSRuntime *rt, gcreason::Reason reason);
|
||||
|
||||
enum GCProgress {
|
||||
/*
|
||||
|
@ -724,12 +755,18 @@ IsIncrementalBarrierNeeded(JSContext *cx);
|
|||
extern JS_FRIEND_API(bool)
|
||||
IsIncrementalBarrierNeededOnObject(JSObject *obj);
|
||||
|
||||
extern JS_FRIEND_API(bool)
|
||||
IsIncrementalBarrierNeededOnScript(JSScript *obj);
|
||||
|
||||
extern JS_FRIEND_API(void)
|
||||
IncrementalReferenceBarrier(void *ptr);
|
||||
|
||||
extern JS_FRIEND_API(void)
|
||||
IncrementalValueBarrier(const Value &v);
|
||||
|
||||
extern JS_FRIEND_API(void)
|
||||
PokeGC(JSRuntime *rt);
|
||||
|
||||
class ObjectPtr
|
||||
{
|
||||
JSObject *value;
|
||||
|
@ -790,6 +827,16 @@ CastToJSFreeOp(FreeOp *fop)
|
|||
extern JS_FRIEND_API(const jschar*)
|
||||
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 */
|
||||
|
||||
#endif
|
||||
|
@ -963,6 +1010,16 @@ JS_NewArrayBuffer(JSContext *cx, uint32_t nbytes);
|
|||
extern JS_FRIEND_API(JSBool)
|
||||
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)
|
||||
*/
|
||||
|
@ -1063,6 +1120,14 @@ JS_GetTypedArrayByteOffset(JSObject *obj, JSContext *cx);
|
|||
extern JS_FRIEND_API(uint32_t)
|
||||
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
|
||||
*/
|
||||
|
@ -1106,4 +1171,46 @@ JS_GetFloat64ArrayData(JSObject *obj, JSContext *cx);
|
|||
extern JS_FRIEND_API(void *)
|
||||
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___ */
|
||||
|
|
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 -*-
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
* This 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 jshash_h___
|
||||
#define jshash_h___
|
||||
|
|
|
@ -1,41 +1,8 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
* This 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 jslock_h__
|
||||
#define jslock_h__
|
||||
|
||||
|
@ -56,6 +23,10 @@
|
|||
|
||||
#else /* JS_THREADSAFE */
|
||||
|
||||
typedef struct PRThread PRThread;
|
||||
typedef struct PRCondVar PRCondVar;
|
||||
typedef struct PRLock PRLock;
|
||||
|
||||
# define JS_ATOMIC_INCREMENT(p) (++*(p))
|
||||
# define JS_ATOMIC_DECREMENT(p) (--*(p))
|
||||
# define JS_ATOMIC_ADD(p,v) (*(p) += (v))
|
||||
|
|
|
@ -1,39 +1,6 @@
|
|||
/* ***** 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 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 ***** */
|
||||
/* 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 json_h___
|
||||
#define json_h___
|
||||
|
@ -50,9 +17,14 @@ extern JSObject *
|
|||
js_InitJSONClass(JSContext *cx, JSObject *obj);
|
||||
|
||||
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);
|
||||
|
||||
// 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;
|
||||
* 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 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* the Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Zack Weinberg <zweinberg@mozilla.com> (original author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/* 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 jsperf_h___
|
||||
#define jsperf_h___
|
||||
|
|
|
@ -1,40 +1,7 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/* This 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 jsprf_h___
|
||||
#define jsprf_h___
|
||||
|
|
|
@ -1,40 +1,9 @@
|
|||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set sw=4 ts=8 et tw=80 ft=c:
|
||||
*
|
||||
* ***** 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 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 ***** */
|
||||
* 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/. */
|
||||
|
||||
#include "jsversion.h"
|
||||
|
||||
|
@ -94,6 +63,7 @@ JS_PROTO(AnyName, 35, js_InitNullClass)
|
|||
JS_PROTO(WeakMap, 36, js_InitWeakMapClass)
|
||||
JS_PROTO(Map, 37, js_InitMapClass)
|
||||
JS_PROTO(Set, 38, js_InitSetClass)
|
||||
JS_PROTO(DataView, 39, js_InitTypedArrayClasses)
|
||||
|
||||
#undef XML_INIT
|
||||
#undef NAMESPACE_INIT
|
||||
|
|
|
@ -1,43 +1,9 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=4 sw=4 et tw=99:
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released
|
||||
* May 28, 2008.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Foundation
|
||||
* Portions created by the Initial Developer are Copyright (C) 2009
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Andreas Gal <gal@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
* 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 jsproxy_h___
|
||||
#define jsproxy_h___
|
||||
|
@ -47,33 +13,91 @@
|
|||
|
||||
namespace js {
|
||||
|
||||
/* Base class for all C++ proxy handlers. */
|
||||
class JS_FRIEND_API(ProxyHandler) {
|
||||
class Wrapper;
|
||||
|
||||
/*
|
||||
* 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;
|
||||
public:
|
||||
explicit ProxyHandler(void *family);
|
||||
virtual ~ProxyHandler();
|
||||
explicit BaseProxyHandler(void *family);
|
||||
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. */
|
||||
virtual bool getPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id, bool set,
|
||||
PropertyDescriptor *desc) = 0;
|
||||
virtual bool getOwnPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id, bool set,
|
||||
virtual bool getPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id,
|
||||
bool set, PropertyDescriptor *desc) = 0;
|
||||
virtual bool getOwnPropertyDescriptor(JSContext *cx, JSObject *proxy,
|
||||
jsid id, bool set,
|
||||
PropertyDescriptor *desc) = 0;
|
||||
virtual bool defineProperty(JSContext *cx, JSObject *proxy, jsid id,
|
||||
PropertyDescriptor *desc) = 0;
|
||||
virtual bool getOwnPropertyNames(JSContext *cx, JSObject *proxy, AutoIdVector &props) = 0;
|
||||
virtual bool getOwnPropertyNames(JSContext *cx, JSObject *proxy,
|
||||
AutoIdVector &props) = 0;
|
||||
virtual bool delete_(JSContext *cx, JSObject *proxy, jsid id, bool *bp) = 0;
|
||||
virtual bool enumerate(JSContext *cx, JSObject *proxy, AutoIdVector &props) = 0;
|
||||
virtual bool fix(JSContext *cx, JSObject *proxy, Value *vp) = 0;
|
||||
virtual bool enumerate(JSContext *cx, JSObject *proxy,
|
||||
AutoIdVector &props) = 0;
|
||||
|
||||
/* ES5 Harmony derived proxy traps. */
|
||||
virtual bool has(JSContext *cx, JSObject *proxy, jsid id, bool *bp);
|
||||
virtual bool hasOwn(JSContext *cx, JSObject *proxy, jsid id, bool *bp);
|
||||
virtual bool get(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id, Value *vp);
|
||||
virtual bool set(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id, bool strict,
|
||||
Value *vp);
|
||||
virtual bool get(JSContext *cx, JSObject *proxy, JSObject *receiver,
|
||||
jsid id, Value *vp);
|
||||
virtual bool set(JSContext *cx, JSObject *proxy, JSObject *receiver,
|
||||
jsid id, bool strict, Value *vp);
|
||||
virtual bool keys(JSContext *cx, JSObject *proxy, AutoIdVector &props);
|
||||
virtual bool iterate(JSContext *cx, JSObject *proxy, unsigned flags, Value *vp);
|
||||
virtual bool iterate(JSContext *cx, JSObject *proxy, unsigned flags,
|
||||
Value *vp);
|
||||
|
||||
/* Spidermonkey extensions. */
|
||||
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 iteratorNext(JSContext *cx, JSObject *proxy, Value *vp);
|
||||
virtual void finalize(JSFreeOp *fop, JSObject *proxy);
|
||||
virtual void trace(JSTracer *trc, JSObject *proxy);
|
||||
virtual bool getElementIfPresent(JSContext *cx, JSObject *obj, JSObject *receiver,
|
||||
uint32_t index, Value *vp, bool *present);
|
||||
};
|
||||
|
||||
virtual bool isOuterWindow() {
|
||||
return false;
|
||||
}
|
||||
/*
|
||||
* 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() {
|
||||
return mFamily;
|
||||
}
|
||||
/* ES5 Harmony fundamental proxy traps. */
|
||||
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. */
|
||||
|
@ -117,7 +211,6 @@ class Proxy {
|
|||
static bool getOwnPropertyNames(JSContext *cx, JSObject *proxy, AutoIdVector &props);
|
||||
static bool delete_(JSContext *cx, JSObject *proxy, jsid id, bool *bp);
|
||||
static bool enumerate(JSContext *cx, JSObject *proxy, AutoIdVector &props);
|
||||
static bool fix(JSContext *cx, JSObject *proxy, Value *vp);
|
||||
|
||||
/* ES5 Harmony derived proxy traps. */
|
||||
static bool has(JSContext *cx, JSObject *proxy, jsid id, bool *bp);
|
||||
|
@ -178,11 +271,11 @@ const uint32_t JSSLOT_PROXY_EXTRA = 2;
|
|||
const uint32_t JSSLOT_PROXY_CALL = 4;
|
||||
const uint32_t JSSLOT_PROXY_CONSTRUCT = 5;
|
||||
|
||||
inline ProxyHandler *
|
||||
inline BaseProxyHandler *
|
||||
GetProxyHandler(const JSObject *obj)
|
||||
{
|
||||
JS_ASSERT(IsProxy(obj));
|
||||
return (ProxyHandler *) GetReservedSlot(obj, JSSLOT_PROXY_HANDLER).toPrivate();
|
||||
return (BaseProxyHandler *) GetReservedSlot(obj, JSSLOT_PROXY_HANDLER).toPrivate();
|
||||
}
|
||||
|
||||
inline const Value &
|
||||
|
@ -192,6 +285,20 @@ GetProxyPrivate(const JSObject *obj)
|
|||
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 &
|
||||
GetProxyExtra(const JSObject *obj, size_t n)
|
||||
{
|
||||
|
@ -200,16 +307,7 @@ GetProxyExtra(const JSObject *obj, size_t n)
|
|||
}
|
||||
|
||||
inline void
|
||||
SetProxyExtra(JSObject *obj, size_t n, const Value &extra)
|
||||
{
|
||||
JS_ASSERT(IsProxy(obj));
|
||||
JS_ASSERT(n <= 1);
|
||||
SetReservedSlot(obj, JSSLOT_PROXY_EXTRA + n, extra);
|
||||
}
|
||||
|
||||
|
||||
inline void
|
||||
SetProxyHandler(JSObject *obj, ProxyHandler *handler)
|
||||
SetProxyHandler(JSObject *obj, BaseProxyHandler *handler)
|
||||
{
|
||||
JS_ASSERT(IsProxy(obj));
|
||||
SetReservedSlot(obj, JSSLOT_PROXY_HANDLER, PrivateValue(handler));
|
||||
|
@ -222,8 +320,16 @@ SetProxyPrivate(JSObject *obj, const Value &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 *)
|
||||
NewProxyObject(JSContext *cx, ProxyHandler *handler, const Value &priv,
|
||||
NewProxyObject(JSContext *cx, BaseProxyHandler *handler, const Value &priv,
|
||||
JSObject *proto, JSObject *parent,
|
||||
JSObject *call = NULL, JSObject *construct = NULL);
|
||||
|
||||
|
|
|
@ -1,41 +1,8 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
* This 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 jsprvtd_h___
|
||||
#define jsprvtd_h___
|
||||
|
@ -84,7 +51,6 @@ typedef struct JSArgumentFormatMap JSArgumentFormatMap;
|
|||
typedef struct JSGCThing JSGCThing;
|
||||
typedef struct JSGenerator JSGenerator;
|
||||
typedef struct JSNativeEnumerator JSNativeEnumerator;
|
||||
typedef struct JSProperty JSProperty;
|
||||
typedef struct JSSharpObjectMap JSSharpObjectMap;
|
||||
typedef struct JSTryNote JSTryNote;
|
||||
|
||||
|
@ -95,7 +61,10 @@ typedef struct JSPrinter JSPrinter;
|
|||
typedef struct JSStackHeader JSStackHeader;
|
||||
typedef struct JSSubString JSSubString;
|
||||
typedef struct JSSpecializedNative JSSpecializedNative;
|
||||
|
||||
#if JS_HAS_XML_SUPPORT
|
||||
typedef struct JSXML JSXML;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Template declarations.
|
||||
|
@ -160,9 +129,7 @@ class StackFrame;
|
|||
class StackSegment;
|
||||
class StackSpace;
|
||||
class ContextStack;
|
||||
class FrameRegsIter;
|
||||
class CallReceiver;
|
||||
class CallArgs;
|
||||
class ScriptFrameIter;
|
||||
|
||||
struct BytecodeEmitter;
|
||||
struct Definition;
|
||||
|
@ -170,6 +137,7 @@ struct FunctionBox;
|
|||
struct ObjectBox;
|
||||
struct ParseNode;
|
||||
struct Parser;
|
||||
struct SharedContext;
|
||||
class TokenStream;
|
||||
struct Token;
|
||||
struct TokenPos;
|
||||
|
@ -178,8 +146,8 @@ struct TreeContext;
|
|||
class UpvarCookie;
|
||||
|
||||
class Proxy;
|
||||
class ProxyHandler;
|
||||
class Wrapper;
|
||||
class BaseProxyHandler;
|
||||
class DirectWrapper;
|
||||
class CrossCompartmentWrapper;
|
||||
|
||||
class TempAllocPolicy;
|
||||
|
@ -206,10 +174,9 @@ struct StackShape;
|
|||
|
||||
class MultiDeclRange;
|
||||
class ParseMapPool;
|
||||
class DefnOrHeader;
|
||||
class DefinitionList;
|
||||
typedef InlineMap<JSAtom *, Definition *, 24> AtomDefnMap;
|
||||
typedef InlineMap<JSAtom *, jsatomid, 24> AtomIndexMap;
|
||||
typedef InlineMap<JSAtom *, DefnOrHeader, 24> AtomDOHMap;
|
||||
typedef Vector<UpvarCookie, 8> UpvarCookies;
|
||||
|
||||
class Breakpoint;
|
||||
|
@ -256,17 +223,13 @@ typedef JS::Handle<types::TypeObject*> HandleTypeObject;
|
|||
typedef JS::Handle<JSAtom*> HandleAtom;
|
||||
typedef JS::Handle<PropertyName*> HandlePropertyName;
|
||||
|
||||
typedef JS::Root<Shape*> RootShape;
|
||||
typedef JS::Root<BaseShape*> RootBaseShape;
|
||||
typedef JS::Root<types::TypeObject*> RootTypeObject;
|
||||
typedef JS::Root<JSAtom*> RootAtom;
|
||||
typedef JS::Root<PropertyName*> RootPropertyName;
|
||||
typedef JS::MutableHandle<Shape*> MutableHandleShape;
|
||||
|
||||
typedef JS::RootedVar<Shape*> RootedVarShape;
|
||||
typedef JS::RootedVar<BaseShape*> RootedVarBaseShape;
|
||||
typedef JS::RootedVar<types::TypeObject*> RootedVarTypeObject;
|
||||
typedef JS::RootedVar<JSAtom*> RootedVarAtom;
|
||||
typedef JS::RootedVar<PropertyName*> RootedVarPropertyName;
|
||||
typedef JS::Rooted<Shape*> RootedShape;
|
||||
typedef JS::Rooted<BaseShape*> RootedBaseShape;
|
||||
typedef JS::Rooted<types::TypeObject*> RootedTypeObject;
|
||||
typedef JS::Rooted<JSAtom*> RootedAtom;
|
||||
typedef JS::Rooted<PropertyName*> RootedPropertyName;
|
||||
|
||||
enum XDRMode {
|
||||
XDR_ENCODE,
|
||||
|
@ -404,41 +367,23 @@ typedef struct JSDebugHooks {
|
|||
|
||||
/* js::ObjectOps function pointer typedefs. */
|
||||
|
||||
/*
|
||||
* Look for id in obj and its prototype chain, returning false on error or
|
||||
* exception, true on success. On success, return null in *propp if id was
|
||||
* not found. If id was found, return the first object searching from obj
|
||||
* along its prototype chain in which id names a direct property in *objp, and
|
||||
* return a non-null, opaque property pointer in *propp.
|
||||
*
|
||||
* If JSLookupPropOp succeeds and returns with *propp non-null, that pointer
|
||||
* may be passed as the prop parameter to a JSAttributesOp, as a short-cut
|
||||
* that bypasses id re-lookup.
|
||||
*/
|
||||
typedef JSBool
|
||||
(* JSLookupPropOp)(JSContext *cx, JSObject *obj, jsid id, JSObject **objp,
|
||||
JSProperty **propp);
|
||||
|
||||
/*
|
||||
* Get or set attributes of the property obj[id]. Return false on error or
|
||||
* exception, true with current attributes in *attrsp.
|
||||
*/
|
||||
typedef JSBool
|
||||
(* JSAttributesOp)(JSContext *cx, JSObject *obj, jsid id, unsigned *attrsp);
|
||||
|
||||
/*
|
||||
* A generic type for functions mapping an object to another object, or null
|
||||
* if an error or exception was thrown on cx.
|
||||
*/
|
||||
typedef JSObject *
|
||||
(* JSObjectOp)(JSContext *cx, JSObject *obj);
|
||||
(* 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
|
||||
* iterator object or null if an error or exception was thrown on cx.
|
||||
*/
|
||||
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
|
||||
|
|
|
@ -1,41 +1,8 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
* This 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 jspubtd_h___
|
||||
#define jspubtd_h___
|
||||
|
@ -148,7 +115,11 @@ typedef enum JSProtoKey {
|
|||
/* js_CheckAccess mode enumeration. */
|
||||
typedef enum JSAccessMode {
|
||||
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,
|
||||
|
@ -249,7 +220,7 @@ JS_END_EXTERN_C
|
|||
namespace JS {
|
||||
|
||||
template <typename T>
|
||||
class Root;
|
||||
class Rooted;
|
||||
|
||||
class SkipRoot;
|
||||
|
||||
|
@ -261,8 +232,11 @@ enum ThingRootKind
|
|||
THING_ROOT_TYPE_OBJECT,
|
||||
THING_ROOT_STRING,
|
||||
THING_ROOT_SCRIPT,
|
||||
THING_ROOT_XML,
|
||||
THING_ROOT_ID,
|
||||
THING_ROOT_PROPERTY_ID,
|
||||
THING_ROOT_VALUE,
|
||||
THING_ROOT_TYPE,
|
||||
THING_ROOT_LIMIT
|
||||
};
|
||||
|
||||
|
@ -280,15 +254,15 @@ struct ContextFriendFields {
|
|||
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
|
||||
* 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
|
||||
* GC heap pointers (where the target is rooted somewhere else) or integer
|
||||
|
@ -299,8 +273,6 @@ struct ContextFriendFields {
|
|||
*/
|
||||
SkipRoot *skipGCRooters;
|
||||
#endif
|
||||
|
||||
#endif /* JSGC_ROOT_ANALYSIS */
|
||||
};
|
||||
|
||||
} /* 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 -*- */
|
||||
/* ***** 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):
|
||||
* 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 ***** */
|
||||
/* 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/. */
|
||||
|
||||
/*
|
||||
** File: jstypes.h
|
||||
|
|
|
@ -1,41 +1,8 @@
|
|||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
* This 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/. */
|
||||
|
||||
/*
|
||||
* PR assertion checker.
|
||||
|
@ -410,14 +377,8 @@ inline __attribute__ ((unused)) void MUST_FLOW_THROUGH(const char *label) {}
|
|||
#endif
|
||||
#ifdef JS_CRASH_DIAGNOSTICS
|
||||
# define JS_POISON(p, val, size) memset((p), (val), (size))
|
||||
# define JS_OPT_ASSERT(expr) \
|
||||
((expr) ? (void)0 : MOZ_Assert(#expr, __FILE__, __LINE__))
|
||||
# define JS_OPT_ASSERT_IF(cond, expr) \
|
||||
((!(cond) || (expr)) ? (void)0 : MOZ_Assert(#expr, __FILE__, __LINE__))
|
||||
#else
|
||||
# define JS_POISON(p, val, size) ((void) 0)
|
||||
# define JS_OPT_ASSERT(expr) ((void) 0)
|
||||
# define JS_OPT_ASSERT_IF(cond, expr) ((void) 0)
|
||||
#endif
|
||||
|
||||
/* Basic stats */
|
||||
|
|
|
@ -1,41 +1,9 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=4 sw=4 et tw=99 ft=cpp:
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is 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 ***** */
|
||||
* 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 jsvalimpl_h__
|
||||
#define jsvalimpl_h__
|
||||
|
@ -44,8 +12,6 @@
|
|||
* Implementation details for js::Value in jsapi.h.
|
||||
*/
|
||||
|
||||
#include "mozilla/FloatingPoint.h"
|
||||
|
||||
#include "js/Utility.h"
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
@ -247,10 +213,11 @@ typedef enum JSWhyMagic
|
|||
JS_ARG_POISON, /* used in debug builds to catch tracing errors */
|
||||
JS_SERIALIZE_NO_NODE, /* an empty subnode in the AST serializer */
|
||||
JS_LAZY_ARGUMENTS, /* lazy arguments value on the stack */
|
||||
JS_UNASSIGNED_ARGUMENTS, /* the initial value of callobj.arguments */
|
||||
JS_OPTIMIZED_ARGUMENTS, /* optimized-away 'arguments' value */
|
||||
JS_IS_CONSTRUCTING, /* magic value passed to natives to indicate construction */
|
||||
JS_OVERWRITTEN_CALLEE, /* arguments.callee has been overwritten */
|
||||
JS_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 */
|
||||
} JSWhyMagic;
|
||||
|
||||
|
@ -269,6 +236,7 @@ typedef union jsval_layout
|
|||
void *ptr;
|
||||
JSWhyMagic why;
|
||||
size_t word;
|
||||
uintptr_t uintptr;
|
||||
} payload;
|
||||
JSValueTag tag;
|
||||
} s;
|
||||
|
@ -296,6 +264,7 @@ typedef union jsval_layout
|
|||
double asDouble;
|
||||
void *asPtr;
|
||||
size_t asWord;
|
||||
uintptr_t asUIntPtr;
|
||||
} JSVAL_ALIGNMENT jsval_layout;
|
||||
# endif /* JS_BITS_PER_WORD */
|
||||
#else /* defined(IS_LITTLE_ENDIAN) */
|
||||
|
@ -314,6 +283,7 @@ typedef union jsval_layout
|
|||
void *ptr;
|
||||
JSWhyMagic why;
|
||||
size_t word;
|
||||
uintptr_t uintptr;
|
||||
} payload;
|
||||
} s;
|
||||
double asDouble;
|
||||
|
@ -338,6 +308,7 @@ typedef union jsval_layout
|
|||
double asDouble;
|
||||
void *asPtr;
|
||||
size_t asWord;
|
||||
uintptr_t asUIntPtr;
|
||||
} JSVAL_ALIGNMENT jsval_layout;
|
||||
# endif /* JS_BITS_PER_WORD */
|
||||
#endif /* defined(IS_LITTLE_ENDIAN) */
|
||||
|
|
|
@ -1,41 +1,8 @@
|
|||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
* This 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/. */
|
||||
|
||||
/*
|
||||
* JS configuration macros.
|
||||
|
@ -91,7 +58,6 @@
|
|||
#define JS_HAS_CONST 0 /* has JS2 const as alternative var */
|
||||
#define JS_HAS_FUN_EXPR_STMT 0 /* has function expression statement */
|
||||
#define JS_HAS_NO_SUCH_METHOD 0 /* has o.__noSuchMethod__ handler */
|
||||
#define JS_HAS_XML_SUPPORT 0 /* has ECMAScript for XML support */
|
||||
#define JS_HAS_GENERATORS 0 /* has yield in generator function */
|
||||
#define JS_HAS_BLOCK_SCOPE 0 /* has block scope via let/arraycomp */
|
||||
#define JS_HAS_DESTRUCTURING 0 /* has [a,b] = ... or {p:a,q:b} = ... */
|
||||
|
@ -113,7 +79,6 @@
|
|||
#define JS_HAS_CONST 1 /* has JS2 const as alternative var */
|
||||
#define JS_HAS_FUN_EXPR_STMT 1 /* has function expression statement */
|
||||
#define JS_HAS_NO_SUCH_METHOD 1 /* has o.__noSuchMethod__ handler */
|
||||
#define JS_HAS_XML_SUPPORT 0 /* has ECMAScript for XML support */
|
||||
#define JS_HAS_GENERATORS 0 /* has yield in generator function */
|
||||
#define JS_HAS_BLOCK_SCOPE 0 /* has block scope via let/arraycomp */
|
||||
#define JS_HAS_DESTRUCTURING 0 /* has [a,b] = ... or {p:a,q:b} = ... */
|
||||
|
@ -131,7 +96,6 @@
|
|||
#define JS_HAS_CONST 1 /* has JS2 const as alternative var */
|
||||
#define JS_HAS_FUN_EXPR_STMT 1 /* has function expression statement */
|
||||
#define JS_HAS_NO_SUCH_METHOD 1 /* has o.__noSuchMethod__ handler */
|
||||
#define JS_HAS_XML_SUPPORT 1 /* has ECMAScript for XML support */
|
||||
#define JS_HAS_GENERATORS 0 /* has yield in generator function */
|
||||
#define JS_HAS_BLOCK_SCOPE 0 /* has block scope via let/arraycomp */
|
||||
#define JS_HAS_DESTRUCTURING 0 /* has [a,b] = ... or {p:a,q:b} = ... */
|
||||
|
@ -149,7 +113,6 @@
|
|||
#define JS_HAS_CONST 1 /* has JS2 const as alternative var */
|
||||
#define JS_HAS_FUN_EXPR_STMT 1 /* has function expression statement */
|
||||
#define JS_HAS_NO_SUCH_METHOD 1 /* has o.__noSuchMethod__ handler */
|
||||
#define JS_HAS_XML_SUPPORT 1 /* has ECMAScript for XML support */
|
||||
#define JS_HAS_GENERATORS 1 /* has yield in generator function */
|
||||
#define JS_HAS_BLOCK_SCOPE 1 /* has block scope via let/arraycomp */
|
||||
#define JS_HAS_DESTRUCTURING 1 /* has [a,b] = ... or {p:a,q:b} = ... */
|
||||
|
@ -167,7 +130,6 @@
|
|||
#define JS_HAS_CONST 1 /* has JS2 const as alternative var */
|
||||
#define JS_HAS_FUN_EXPR_STMT 1 /* has function expression statement */
|
||||
#define JS_HAS_NO_SUCH_METHOD 1 /* has o.__noSuchMethod__ handler */
|
||||
#define JS_HAS_XML_SUPPORT 1 /* has ECMAScript for XML support */
|
||||
#define JS_HAS_GENERATORS 1 /* has yield in generator function */
|
||||
#define JS_HAS_BLOCK_SCOPE 1 /* has block scope via let/arraycomp */
|
||||
#define JS_HAS_DESTRUCTURING 2 /* has [a,b] = ... or {p:a,q:b} = ... */
|
||||
|
|
|
@ -1,43 +1,9 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=4 sw=4 et tw=99:
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released
|
||||
* May 28, 2008.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Foundation
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Andreas Gal <gal@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
* 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 jswrapper_h___
|
||||
#define jswrapper_h___
|
||||
|
@ -51,30 +17,76 @@ namespace js {
|
|||
|
||||
class DummyFrameGuard;
|
||||
|
||||
/* Base class that just implements no-op forwarding methods for fundamental
|
||||
* traps. This is meant to be used as a base class for ProxyHandlers that
|
||||
* want transparent forwarding behavior but don't want to use the derived
|
||||
* traps and other baggage of js::Wrapper.
|
||||
/*
|
||||
* A wrapper is essentially a proxy that restricts access to certain traps. The
|
||||
* way in which a wrapper restricts access to its traps depends on the
|
||||
* 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;
|
||||
|
||||
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. */
|
||||
virtual bool getPropertyDescriptor(JSContext *cx, JSObject *wrapper, jsid id, bool set,
|
||||
PropertyDescriptor *desc) MOZ_OVERRIDE;
|
||||
virtual bool getOwnPropertyDescriptor(JSContext *cx, JSObject *wrapper, jsid id, bool set,
|
||||
PropertyDescriptor *desc) MOZ_OVERRIDE;
|
||||
virtual bool defineProperty(JSContext *cx, JSObject *wrapper, jsid id,
|
||||
PropertyDescriptor *desc) MOZ_OVERRIDE;
|
||||
virtual bool getOwnPropertyNames(JSContext *cx, JSObject *wrapper, AutoIdVector &props) MOZ_OVERRIDE;
|
||||
virtual bool delete_(JSContext *cx, JSObject *wrapper, jsid id, bool *bp) MOZ_OVERRIDE;
|
||||
virtual bool enumerate(JSContext *cx, JSObject *wrapper, AutoIdVector &props) MOZ_OVERRIDE;
|
||||
virtual bool fix(JSContext *cx, JSObject *wrapper, Value *vp) MOZ_OVERRIDE;
|
||||
typedef enum {
|
||||
PermitObjectAccess,
|
||||
PermitPropertyAccess,
|
||||
DenyAccess
|
||||
} Permission;
|
||||
|
||||
static JSObject *New(JSContext *cx, JSObject *obj, JSObject *proto,
|
||||
JSObject *parent, Wrapper *handler);
|
||||
|
||||
static Wrapper *wrapperHandler(const JSObject *wrapper);
|
||||
|
||||
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.
|
||||
*
|
||||
|
@ -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,
|
||||
* |id| is generally JSID_VOID.
|
||||
*
|
||||
* leave() allows the policy to undo various scoped state changes taken in
|
||||
* enter(). If enter() succeeds, leave() must be called upon completion of
|
||||
* the approved action.
|
||||
*
|
||||
* The |act| parameter to enter() specifies the action being performed. GET,
|
||||
* SET, and CALL are self-explanatory, but PUNCTURE requires more explanation:
|
||||
* SET, and CALL are self-explanatory, but PUNCTURE requires more
|
||||
* explanation:
|
||||
*
|
||||
* GET and SET allow for a very fine-grained security membrane, through
|
||||
* which access can be granted or denied on a per-property, per-object, and
|
||||
|
@ -103,24 +112,87 @@ class JS_FRIEND_API(AbstractWrapper) : public ProxyHandler
|
|||
* permission, and thus should generally be denied for security wrappers
|
||||
* except under very special circumstances. When |act| is PUNCTURE, |id|
|
||||
* should be JSID_VOID.
|
||||
* */
|
||||
enum Action { GET, SET, CALL, PUNCTURE };
|
||||
virtual bool enter(JSContext *cx, JSObject *wrapper, jsid id, Action act, bool *bp);
|
||||
virtual void leave(JSContext *cx, JSObject *wrapper);
|
||||
|
||||
static JSObject *wrappedObject(const JSObject *wrapper);
|
||||
static AbstractWrapper *wrapperHandler(const JSObject *wrapper);
|
||||
*/
|
||||
virtual bool enter(JSContext *cx, JSObject *wrapper, jsid id, Action act,
|
||||
bool *bp);
|
||||
};
|
||||
|
||||
/* 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:
|
||||
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. */
|
||||
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 nativeCall(JSContext *cx, JSObject *wrapper, Class *clasp, Native native, CallArgs args) MOZ_OVERRIDE;
|
||||
virtual bool hasInstance(JSContext *cx, JSObject *wrapper, const Value *vp, bool *bp) MOZ_OVERRIDE;
|
||||
virtual JSType typeOf(JSContext *cx, JSObject *proxy) MOZ_OVERRIDE;
|
||||
virtual bool objectClassIs(JSObject *obj, ESClassValue classValue, JSContext *cx) MOZ_OVERRIDE;
|
||||
virtual JSString *obj_toString(JSContext *cx, JSObject *wrapper) MOZ_OVERRIDE;
|
||||
virtual JSString *fun_toString(JSContext *cx, JSObject *wrapper, unsigned indent) MOZ_OVERRIDE;
|
||||
virtual bool regexp_toShared(JSContext *cx, JSObject *proxy, RegExpGuard *g) MOZ_OVERRIDE;
|
||||
virtual bool defaultValue(JSContext *cx, JSObject *wrapper, JSType hint, Value *vp) MOZ_OVERRIDE;
|
||||
virtual bool iteratorNext(JSContext *cx, JSObject *wrapper, Value *vp) MOZ_OVERRIDE;
|
||||
virtual bool defaultValue(JSContext *cx, JSObject *wrapper_, JSType hint,
|
||||
Value *vp) MOZ_OVERRIDE;
|
||||
|
||||
virtual void trace(JSTracer *trc, JSObject *wrapper) MOZ_OVERRIDE;
|
||||
|
||||
using AbstractWrapper::Action;
|
||||
|
||||
static Wrapper singleton;
|
||||
|
||||
static JSObject *New(JSContext *cx, JSObject *obj, JSObject *proto, JSObject *parent,
|
||||
Wrapper *handler);
|
||||
|
||||
using AbstractWrapper::wrappedObject;
|
||||
using AbstractWrapper::wrapperHandler;
|
||||
|
||||
enum {
|
||||
CROSS_COMPARTMENT = 1 << 0,
|
||||
LAST_USED_FLAG = CROSS_COMPARTMENT
|
||||
};
|
||||
static DirectWrapper singleton;
|
||||
|
||||
static void *getWrapperFamily();
|
||||
};
|
||||
|
||||
/* Base class for all cross compartment wrapper handlers. */
|
||||
class JS_FRIEND_API(CrossCompartmentWrapper) : public Wrapper
|
||||
class JS_FRIEND_API(CrossCompartmentWrapper) : public DirectWrapper
|
||||
{
|
||||
public:
|
||||
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 JSString *obj_toString(JSContext *cx, JSObject *wrapper) MOZ_OVERRIDE;
|
||||
virtual JSString *fun_toString(JSContext *cx, JSObject *wrapper, unsigned indent) MOZ_OVERRIDE;
|
||||
virtual bool regexp_toShared(JSContext *cx, JSObject *proxy, RegExpGuard *g) MOZ_OVERRIDE;
|
||||
virtual bool defaultValue(JSContext *cx, JSObject *wrapper, JSType hint, Value *vp) MOZ_OVERRIDE;
|
||||
virtual bool iteratorNext(JSContext *cx, JSObject *wrapper, Value *vp);
|
||||
|
||||
virtual void trace(JSTracer *trc, JSObject *wrapper) MOZ_OVERRIDE;
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
typedef SecurityWrapper<Wrapper> SameCompartmentSecurityWrapper;
|
||||
typedef SecurityWrapper<DirectWrapper> SameCompartmentSecurityWrapper;
|
||||
typedef SecurityWrapper<CrossCompartmentWrapper> CrossCompartmentSecurityWrapper;
|
||||
|
||||
/*
|
||||
|
@ -248,6 +301,43 @@ class JS_FRIEND_API(ForceFrame)
|
|||
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 *
|
||||
TransparentObjectWrapper(JSContext *cx, JSObject *obj, JSObject *wrappedProto, JSObject *parent,
|
||||
unsigned flags);
|
||||
|
@ -266,20 +356,69 @@ IsWrapper(const JSObject *obj)
|
|||
// stopAtOuter is true, then this returns the outer window if it was
|
||||
// previously wrapped. Otherwise, this returns the first object for
|
||||
// which JSObject::isWrapper returns false.
|
||||
JS_FRIEND_API(JSObject *) UnwrapObject(JSObject *obj, bool stopAtOuter = true,
|
||||
unsigned *flagsp = NULL);
|
||||
JS_FRIEND_API(JSObject *)
|
||||
UnwrapObject(JSObject *obj, bool stopAtOuter = true, unsigned *flagsp = NULL);
|
||||
|
||||
// Given a JSObject, returns that object stripped of wrappers. At each stage,
|
||||
// the security wrapper has the opportunity to veto the unwrap. Since checked
|
||||
// code should never be unwrapping outer window wrappers, we always stop at
|
||||
// outer windows.
|
||||
JS_FRIEND_API(JSObject *) UnwrapObjectChecked(JSContext *cx, JSObject *obj);
|
||||
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
|
||||
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 */
|
||||
|
||||
#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 -*-
|
||||
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at:
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Jeff Walden <jwalden+code@mit.edu>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/* -*- 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/. */
|
||||
|
||||
/* Implementations of runtime and static assertion macros for C and C++. */
|
||||
|
||||
|
@ -44,11 +9,27 @@
|
|||
#define mozilla_Assertions_h_
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/Types.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdio.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>
|
||||
#endif
|
||||
#ifdef ANDROID
|
||||
|
@ -140,58 +121,73 @@
|
|||
extern "C" {
|
||||
#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
|
||||
* the MSVS 2010 debugger not to be able to recover a call stack.
|
||||
*/
|
||||
# define MOZ_CRASH() \
|
||||
do { \
|
||||
*((volatile int *) NULL) = 123; \
|
||||
exit(3); \
|
||||
} while (0)
|
||||
#elif defined(ANDROID)
|
||||
/*
|
||||
* On Android, raise(SIGABRT) is handled asynchronously. Seg fault now
|
||||
* so we crash immediately and capture the current call stack. We need
|
||||
* to specifically use the global namespace in the C++ case.
|
||||
* On MSVC use the __debugbreak compiler intrinsic, which produces an inline
|
||||
* (not nested in a system function) breakpoint. This distinctively invokes
|
||||
* Breakpad without requiring system library symbols on all stack-processing
|
||||
* machines, as a nested breakpoint would require. We use TerminateProcess
|
||||
* with the exit code aborting would generate because we don't want to invoke
|
||||
* atexit handlers, destructors, library unload handlers, and so on when our
|
||||
* process might be in a compromised state. We don't use abort() because
|
||||
* it'd cause Windows to annoyingly pop up the process error dialog multiple
|
||||
* times. See bug 345118 and bug 426163.
|
||||
*
|
||||
* (Technically these are Windows requirements, not MSVC requirements. But
|
||||
* practically you need MSVC for debugging, and we only ship builds created
|
||||
* by MSVC, so doing it this way reduces complexity.)
|
||||
*/
|
||||
# ifdef __cplusplus
|
||||
# define MOZ_CRASH() \
|
||||
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(); \
|
||||
} while (0)
|
||||
# else
|
||||
# define MOZ_CRASH() \
|
||||
do { \
|
||||
*((volatile int *) NULL) = 123; \
|
||||
*((volatile int*) NULL) = 123; \
|
||||
abort(); \
|
||||
} while (0)
|
||||
# endif
|
||||
#elif defined(__APPLE__)
|
||||
/*
|
||||
* On Mac OS X, Breakpad ignores signals. Only real Mach exceptions are
|
||||
* trapped.
|
||||
*/
|
||||
# define MOZ_CRASH() \
|
||||
do { \
|
||||
*((volatile int *) NULL) = 123; \
|
||||
raise(SIGABRT); /* In case above statement gets nixed by the optimizer. */ \
|
||||
} while (0)
|
||||
#else
|
||||
# define MOZ_CRASH() \
|
||||
do { \
|
||||
raise(SIGABRT); /* To continue from here in GDB: "signal 0". */ \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
|
||||
extern MFBT_API(void)
|
||||
MOZ_Assert(const char* s, const char* file, int ln);
|
||||
|
||||
/*
|
||||
* Prints |s| as an assertion failure (using file and ln as the location of the
|
||||
* 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
|
||||
MOZ_OutputAssertMessage(const char* s, const char *file, int ln)
|
||||
MOZ_ReportAssertionFailure(const char* s, const char* file, int ln)
|
||||
{
|
||||
#ifdef ANDROID
|
||||
__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) \
|
||||
do { \
|
||||
if (!(expr)) { \
|
||||
MOZ_OutputAssertMessage(#expr, __FILE__, __LINE__); \
|
||||
MOZ_ReportAssertionFailure(#expr, __FILE__, __LINE__); \
|
||||
MOZ_CRASH(); \
|
||||
} \
|
||||
} while (0)
|
||||
|
@ -251,7 +247,7 @@ MOZ_OutputAssertMessage(const char* s, const char *file, int ln)
|
|||
# define MOZ_ASSERT_HELPER2(expr, explain) \
|
||||
do { \
|
||||
if (!(expr)) { \
|
||||
MOZ_OutputAssertMessage(#expr " (" explain ")", __FILE__, __LINE__); \
|
||||
MOZ_ReportAssertionFailure(#expr " (" explain ")", __FILE__, __LINE__); \
|
||||
MOZ_CRASH(); \
|
||||
} \
|
||||
} 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)
|
||||
#endif
|
||||
|
||||
/* MOZ_NOT_REACHED_MARKER() expands (in compilers which support it) to an
|
||||
* expression which states that it is undefined behavior for the compiler to
|
||||
* reach this point. Most code should probably use the higher level
|
||||
* MOZ_NOT_REACHED (which expands to this when appropriate).
|
||||
/*
|
||||
* MOZ_NOT_REACHED_MARKER() expands to an expression which states that it is
|
||||
* undefined behavior for execution to reach this point. No guarantees are made
|
||||
* 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__)
|
||||
# define MOZ_NOT_REACHED_MARKER() __builtin_unreachable()
|
||||
#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)
|
||||
# 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
|
||||
#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
|
||||
|
||||
/*
|
||||
|
@ -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?");
|
||||
* }
|
||||
*/
|
||||
#if defined(MOZ_NOT_REACHED_MARKER)
|
||||
# if defined(DEBUG)
|
||||
# define MOZ_NOT_REACHED(reason) do { \
|
||||
MOZ_Assert(reason, __FILE__, __LINE__); \
|
||||
MOZ_NOT_REACHED_MARKER(); \
|
||||
} while (0)
|
||||
# else
|
||||
# define MOZ_NOT_REACHED(reason) MOZ_NOT_REACHED_MARKER()
|
||||
# endif
|
||||
#if defined(DEBUG)
|
||||
# define MOZ_NOT_REACHED(reason) \
|
||||
do { \
|
||||
MOZ_ASSERT(false, reason); \
|
||||
MOZ_NOT_REACHED_MARKER(); \
|
||||
} while (0)
|
||||
#else
|
||||
# if defined(__GNUC__)
|
||||
/*
|
||||
* On older versions of gcc we need to call a noreturn function to mark the
|
||||
* code as unreachable. Since what we want is an unreachable version of
|
||||
* MOZ_Assert, we use an asm label
|
||||
* (http://gcc.gnu.org/onlinedocs/gcc-4.6.2/gcc/Asm-Labels.html) to create
|
||||
* a new declaration to the same symbol. MOZ_ASSERT_NR should only be
|
||||
* used via this macro, as it is a very specific hack to older versions of
|
||||
* gcc.
|
||||
*/
|
||||
# define MOZ_GETASMPREFIX2(X) #X
|
||||
# define MOZ_GETASMPREFIX(X) MOZ_GETASMPREFIX2(X)
|
||||
# define MOZ_ASMPREFIX MOZ_GETASMPREFIX(__USER_LABEL_PREFIX__)
|
||||
extern MOZ_NORETURN MFBT_API(void)
|
||||
MOZ_ASSERT_NR(const char* s, const char* file, int ln) \
|
||||
asm (MOZ_ASMPREFIX "MOZ_Assert");
|
||||
|
||||
# define MOZ_NOT_REACHED(reason) MOZ_ASSERT_NR(reason, __FILE__, __LINE__)
|
||||
# elif defined(DEBUG)
|
||||
# define MOZ_NOT_REACHED(reason) MOZ_Assert(reason, __FILE__, __LINE__)
|
||||
# else
|
||||
# define MOZ_NOT_REACHED(reason) ((void)0)
|
||||
# endif
|
||||
# define MOZ_NOT_REACHED(reason) MOZ_NOT_REACHED_MARKER()
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
|
@ -1,42 +1,7 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at:
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Jeff Walden <jwalden+code@mit.edu> (original author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/* -*- 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/. */
|
||||
|
||||
/* Implementations of various class and method modifier attributes. */
|
||||
|
||||
|
@ -180,6 +145,19 @@
|
|||
# define MOZ_NORETURN /* no support */
|
||||
#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
|
||||
|
||||
/*
|
||||
|
|
|
@ -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
|
||||
* 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/. */
|
||||
|
@ -52,7 +52,8 @@ namespace mozilla {
|
|||
*/
|
||||
|
||||
template<unsigned KeySize, class T>
|
||||
class BloomFilter {
|
||||
class BloomFilter
|
||||
{
|
||||
/*
|
||||
* A counting Bloom filter with 8-bit counters. For now we assume
|
||||
* that having two hash functions is enough, but we may revisit that
|
||||
|
@ -101,7 +102,7 @@ class BloomFilter {
|
|||
* positive rate for N == 100 and to quite bad false positive
|
||||
* rates for larger N.
|
||||
*/
|
||||
public:
|
||||
public:
|
||||
BloomFilter() {
|
||||
MOZ_STATIC_ASSERT(KeySize <= keyShift, "KeySize too big");
|
||||
|
||||
|
@ -142,7 +143,7 @@ public:
|
|||
void remove(uint32_t hash);
|
||||
bool mightContain(uint32_t hash) const;
|
||||
|
||||
private:
|
||||
private:
|
||||
static const size_t arraySize = (1 << KeySize);
|
||||
static const uint32_t keyMask = (1 << KeySize) - 1;
|
||||
static const uint32_t keyShift = 16;
|
||||
|
@ -164,67 +165,67 @@ template<unsigned KeySize, class T>
|
|||
inline void
|
||||
BloomFilter<KeySize, T>::clear()
|
||||
{
|
||||
memset(counters, 0, arraySize);
|
||||
memset(counters, 0, arraySize);
|
||||
}
|
||||
|
||||
template<unsigned KeySize, class T>
|
||||
inline void
|
||||
BloomFilter<KeySize, T>::add(uint32_t hash)
|
||||
{
|
||||
uint8_t& slot1 = firstSlot(hash);
|
||||
if (MOZ_LIKELY(!full(slot1)))
|
||||
++slot1;
|
||||
uint8_t& slot1 = firstSlot(hash);
|
||||
if (MOZ_LIKELY(!full(slot1)))
|
||||
++slot1;
|
||||
|
||||
uint8_t& slot2 = secondSlot(hash);
|
||||
if (MOZ_LIKELY(!full(slot2)))
|
||||
++slot2;
|
||||
uint8_t& slot2 = secondSlot(hash);
|
||||
if (MOZ_LIKELY(!full(slot2)))
|
||||
++slot2;
|
||||
}
|
||||
|
||||
template<unsigned KeySize, class T>
|
||||
MOZ_ALWAYS_INLINE void
|
||||
BloomFilter<KeySize, T>::add(const T* t)
|
||||
{
|
||||
uint32_t hash = t->hash();
|
||||
return add(hash);
|
||||
uint32_t hash = t->hash();
|
||||
return add(hash);
|
||||
}
|
||||
|
||||
template<unsigned KeySize, class T>
|
||||
inline void
|
||||
BloomFilter<KeySize, T>::remove(uint32_t hash)
|
||||
{
|
||||
// If the slots are full, we don't know whether we bumped them to be
|
||||
// there when we added or not, so just leave them full.
|
||||
uint8_t& slot1 = firstSlot(hash);
|
||||
if (MOZ_LIKELY(!full(slot1)))
|
||||
--slot1;
|
||||
// If the slots are full, we don't know whether we bumped them to be
|
||||
// there when we added or not, so just leave them full.
|
||||
uint8_t& slot1 = firstSlot(hash);
|
||||
if (MOZ_LIKELY(!full(slot1)))
|
||||
--slot1;
|
||||
|
||||
uint8_t& slot2 = secondSlot(hash);
|
||||
if (MOZ_LIKELY(!full(slot2)))
|
||||
--slot2;
|
||||
uint8_t& slot2 = secondSlot(hash);
|
||||
if (MOZ_LIKELY(!full(slot2)))
|
||||
--slot2;
|
||||
}
|
||||
|
||||
template<unsigned KeySize, class T>
|
||||
MOZ_ALWAYS_INLINE void
|
||||
BloomFilter<KeySize, T>::remove(const T* t)
|
||||
{
|
||||
uint32_t hash = t->hash();
|
||||
remove(hash);
|
||||
uint32_t hash = t->hash();
|
||||
remove(hash);
|
||||
}
|
||||
|
||||
template<unsigned KeySize, class T>
|
||||
MOZ_ALWAYS_INLINE bool
|
||||
BloomFilter<KeySize, T>::mightContain(uint32_t hash) const
|
||||
{
|
||||
// Check that all the slots for this hash contain something
|
||||
return firstSlot(hash) && secondSlot(hash);
|
||||
// Check that all the slots for this hash contain something
|
||||
return firstSlot(hash) && secondSlot(hash);
|
||||
}
|
||||
|
||||
template<unsigned KeySize, class T>
|
||||
MOZ_ALWAYS_INLINE bool
|
||||
BloomFilter<KeySize, T>::mightContain(const T* t) const
|
||||
{
|
||||
uint32_t hash = t->hash();
|
||||
return mightContain(hash);
|
||||
uint32_t hash = t->hash();
|
||||
return mightContain(hash);
|
||||
}
|
||||
|
||||
} // 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;
|
||||
}
|
||||
|
||||
/** Computes a 32-bit hash of the given double. */
|
||||
static MOZ_ALWAYS_INLINE uint32_t
|
||||
MOZ_HASH_DOUBLE(double d)
|
||||
{
|
||||
union MozDoublePun pun;
|
||||
pun.d = d;
|
||||
|
||||
return ((uint32_t)(pun.u >> 32)) ^ ((uint32_t)(pun.u));
|
||||
}
|
||||
|
||||
static MOZ_ALWAYS_INLINE int
|
||||
MOZ_DOUBLE_IS_INT32(double d, int32_t* i)
|
||||
{
|
||||
|
|
|
@ -1,42 +1,7 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* vim: set ts=8 sw=4 et tw=99 ft=cpp: */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* the Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* L. David Baron <dbaron@dbaron.org>, Mozilla Corporation (original author)
|
||||
* Ms2ger <ms2ger@gmail.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/* -*- 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/. */
|
||||
|
||||
/* Implementation of macros to ensure correct use of RAII Auto* objects. */
|
||||
|
||||
|
@ -52,6 +17,7 @@
|
|||
|
||||
namespace mozilla {
|
||||
namespace detail {
|
||||
|
||||
/*
|
||||
* The following classes are designed to cause assertions to detect
|
||||
* 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
|
||||
* might be:
|
||||
*
|
||||
* AutoRestore savePainting(mIsPainting);
|
||||
* AutoRestore savePainting(mIsPainting);
|
||||
*
|
||||
* but is is easy to accidentally write:
|
||||
*
|
||||
* AutoRestore(mIsPainting);
|
||||
* AutoRestore(mIsPainting);
|
||||
*
|
||||
* which compiles just fine, but runs the destructor well before the
|
||||
* intended time.
|
||||
|
@ -106,14 +72,14 @@ class MOZ_EXPORT_API(GuardObjectNotifier)
|
|||
bool* statementDone;
|
||||
|
||||
public:
|
||||
GuardObjectNotifier() : statementDone(NULL) {}
|
||||
GuardObjectNotifier() : statementDone(NULL) { }
|
||||
|
||||
~GuardObjectNotifier() {
|
||||
*statementDone = true;
|
||||
*statementDone = true;
|
||||
}
|
||||
|
||||
void setStatementDone(bool* statementIsDone) {
|
||||
statementDone = statementIsDone;
|
||||
statementDone = statementIsDone;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -123,25 +89,24 @@ class MOZ_EXPORT_API(GuardObjectNotificationReceiver)
|
|||
bool statementDone;
|
||||
|
||||
public:
|
||||
GuardObjectNotificationReceiver() : statementDone(false) {}
|
||||
GuardObjectNotificationReceiver() : statementDone(false) { }
|
||||
|
||||
~GuardObjectNotificationReceiver() {
|
||||
/*
|
||||
* Assert that the guard object was not used as a temporary.
|
||||
* (Note that this assert might also fire if init is not called
|
||||
* because the guard object's implementation is not using the
|
||||
* above macros correctly.)
|
||||
*/
|
||||
MOZ_ASSERT(statementDone);
|
||||
/*
|
||||
* Assert that the guard object was not used as a temporary. (Note that
|
||||
* this assert might also fire if init is not called because the guard
|
||||
* object's implementation is not using the above macros correctly.)
|
||||
*/
|
||||
MOZ_ASSERT(statementDone);
|
||||
}
|
||||
|
||||
void init(const GuardObjectNotifier& constNotifier) {
|
||||
/*
|
||||
* constNotifier is passed as a const reference so that we can pass a
|
||||
* temporary, but we really intend it as non-const.
|
||||
*/
|
||||
GuardObjectNotifier& notifier = const_cast<GuardObjectNotifier&>(constNotifier);
|
||||
notifier.setStatementDone(&statementDone);
|
||||
/*
|
||||
* constNotifier is passed as a const reference so that we can pass a
|
||||
* temporary, but we really intend it as non-const.
|
||||
*/
|
||||
GuardObjectNotifier& notifier = const_cast<GuardObjectNotifier&>(constNotifier);
|
||||
notifier.setStatementDone(&statementDone);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
/* -*- 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
|
||||
/* -*- 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/. */
|
||||
|
||||
/* Utilities for hashing */
|
||||
/* Utilities for hashing. */
|
||||
|
||||
/*
|
||||
* 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:
|
||||
*
|
||||
* class ComplexObject {
|
||||
* char* str;
|
||||
* uint32_t uint1, uint2;
|
||||
* void (*callbackFn)();
|
||||
* class ComplexObject
|
||||
* {
|
||||
* char* str;
|
||||
* uint32_t uint1, uint2;
|
||||
* void (*callbackFn)();
|
||||
*
|
||||
* uint32_t Hash() {
|
||||
* uint32_t hash = HashString(str);
|
||||
* hash = AddToHash(hash, uint1, uint2);
|
||||
* return AddToHash(hash, callbackFn);
|
||||
* }
|
||||
* public:
|
||||
* uint32_t hash() {
|
||||
* uint32_t hash = HashString(str);
|
||||
* hash = AddToHash(hash, uint1, uint2);
|
||||
* return AddToHash(hash, callbackFn);
|
||||
* }
|
||||
* };
|
||||
*
|
||||
* If you want to hash an nsAString or nsACString, use the HashString functions
|
||||
|
@ -48,6 +48,7 @@
|
|||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/StandardInteger.h"
|
||||
#include "mozilla/Types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
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
|
||||
* 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/. */
|
||||
|
@ -7,8 +8,8 @@
|
|||
* boolean predicate should be branch-predicted.
|
||||
*/
|
||||
|
||||
#ifndef Likely_h_
|
||||
#define Likely_h_
|
||||
#ifndef mozilla_Likely_h_
|
||||
#define mozilla_Likely_h_
|
||||
|
||||
#if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 2))
|
||||
# define MOZ_LIKELY(x) (__builtin_expect((x), 1))
|
||||
|
@ -18,4 +19,4 @@
|
|||
# define MOZ_UNLIKELY(x) (x)
|
||||
#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 -*-
|
||||
* vim: set ts=4 sw=4 tw=80 et cin:
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at:
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation
|
||||
* Portions created by the Initial Developer are Copyright (C) 2012
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Justin Lebar <justin.lebar@gmail.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/* -*- 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/. */
|
||||
|
||||
/* A type-safe doubly-linked list class. */
|
||||
|
||||
|
@ -53,36 +18,30 @@
|
|||
*
|
||||
* class Observer : public LinkedListElement<Observer>
|
||||
* {
|
||||
* void observe(char* topic) { ... }
|
||||
* public:
|
||||
* void observe(char* topic) { ... }
|
||||
* };
|
||||
*
|
||||
* class ObserverContainer
|
||||
* {
|
||||
* private:
|
||||
* LinkedList<ElemType> list;
|
||||
* private:
|
||||
* LinkedList<Observer> list;
|
||||
*
|
||||
* public:
|
||||
*
|
||||
* void addObserver(Observer* observer)
|
||||
* {
|
||||
* // Will assert if |observer| is part of another list.
|
||||
* list.insertBack(observer);
|
||||
* }
|
||||
*
|
||||
* void removeObserver(Observer* observer)
|
||||
* {
|
||||
* // Will assert if |observer| is not part of some list.
|
||||
* observer.remove();
|
||||
* }
|
||||
*
|
||||
* void notifyObservers(char* topic)
|
||||
* {
|
||||
* for (Observer* o = list.getFirst();
|
||||
* o != NULL;
|
||||
* o = o->getNext()) {
|
||||
* o->Observe(topic);
|
||||
* public:
|
||||
* void addObserver(Observer* observer) {
|
||||
* // Will assert if |observer| is part of another list.
|
||||
* list.insertBack(observer);
|
||||
* }
|
||||
*
|
||||
* void removeObserver(Observer* observer) {
|
||||
* // Will assert if |observer| is not part of some list.
|
||||
* observer.remove();
|
||||
* }
|
||||
*
|
||||
* void notifyObservers(char* topic) {
|
||||
* for (Observer* o = list.getFirst(); o != NULL; o = o->getNext())
|
||||
* o->Observe(topic);
|
||||
* }
|
||||
* }
|
||||
* };
|
||||
*
|
||||
*/
|
||||
|
@ -137,43 +96,41 @@ class LinkedListElement
|
|||
* lists, and supporting this painlessly was a key design criterion.
|
||||
*/
|
||||
|
||||
private:
|
||||
private:
|
||||
LinkedListElement* next;
|
||||
LinkedListElement* prev;
|
||||
const bool isSentinel;
|
||||
|
||||
public:
|
||||
LinkedListElement()
|
||||
: next(this)
|
||||
, prev(this)
|
||||
, isSentinel(false)
|
||||
{
|
||||
}
|
||||
public:
|
||||
LinkedListElement() : next(this), prev(this), isSentinel(false) { }
|
||||
|
||||
/*
|
||||
* Get the next element in the list, or NULL if this is the last element in
|
||||
* the list.
|
||||
*/
|
||||
T* getNext()
|
||||
{
|
||||
return next->asT();
|
||||
T* getNext() {
|
||||
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
|
||||
* in the list.
|
||||
*/
|
||||
T* getPrevious()
|
||||
{
|
||||
return prev->asT();
|
||||
T* getPrevious() {
|
||||
return prev->asT();
|
||||
}
|
||||
const T* getPrevious() const {
|
||||
return prev->asT();
|
||||
}
|
||||
|
||||
/*
|
||||
* Insert elem after this element in the list. |this| must be part of a
|
||||
* linked list when you call setNext(); otherwise, this method will assert.
|
||||
*/
|
||||
void setNext(T* elem)
|
||||
{
|
||||
void setNext(T* elem) {
|
||||
MOZ_ASSERT(isInList());
|
||||
setNextUnsafe(elem);
|
||||
}
|
||||
|
@ -183,50 +140,44 @@ public:
|
|||
* linked list when you call setPrevious(); otherwise, this method will
|
||||
* assert.
|
||||
*/
|
||||
void setPrevious(T* elem)
|
||||
{
|
||||
MOZ_ASSERT(isInList());
|
||||
setPreviousUnsafe(elem);
|
||||
void setPrevious(T* elem) {
|
||||
MOZ_ASSERT(isInList());
|
||||
setPreviousUnsafe(elem);
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove this element from the list which contains it. If this element is
|
||||
* not currently part of a linked list, this method asserts.
|
||||
*/
|
||||
void remove()
|
||||
{
|
||||
MOZ_ASSERT(isInList());
|
||||
void remove() {
|
||||
MOZ_ASSERT(isInList());
|
||||
|
||||
prev->next = next;
|
||||
next->prev = prev;
|
||||
next = this;
|
||||
prev = this;
|
||||
prev->next = next;
|
||||
next->prev = prev;
|
||||
next = this;
|
||||
prev = this;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return true if |this| part is of a linked list, and false otherwise.
|
||||
*/
|
||||
bool isInList()
|
||||
{
|
||||
MOZ_ASSERT((next == this) == (prev == this));
|
||||
return next != this;
|
||||
bool isInList() const {
|
||||
MOZ_ASSERT((next == this) == (prev == this));
|
||||
return next != this;
|
||||
}
|
||||
|
||||
private:
|
||||
LinkedListElement& operator=(const LinkedList<T>& other) MOZ_DELETE;
|
||||
LinkedListElement(const LinkedList<T>& other) MOZ_DELETE;
|
||||
|
||||
private:
|
||||
friend class LinkedList<T>;
|
||||
|
||||
enum NodeKind {
|
||||
NODE_KIND_NORMAL,
|
||||
NODE_KIND_SENTINEL
|
||||
NODE_KIND_NORMAL,
|
||||
NODE_KIND_SENTINEL
|
||||
};
|
||||
|
||||
LinkedListElement(NodeKind nodeKind)
|
||||
: next(this)
|
||||
, prev(this)
|
||||
, isSentinel(nodeKind == NODE_KIND_SENTINEL)
|
||||
: next(this),
|
||||
prev(this),
|
||||
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
|
||||
* a sentinel node.
|
||||
*/
|
||||
T* asT()
|
||||
{
|
||||
if (isSentinel)
|
||||
return NULL;
|
||||
T* asT() {
|
||||
if (isSentinel)
|
||||
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
|
||||
* the list. This is called by LinkedList::insertFront().
|
||||
*/
|
||||
void setNextUnsafe(T* elem)
|
||||
{
|
||||
LinkedListElement *listElem = static_cast<LinkedListElement*>(elem);
|
||||
MOZ_ASSERT(!listElem->isInList());
|
||||
void setNextUnsafe(T* elem) {
|
||||
LinkedListElement *listElem = static_cast<LinkedListElement*>(elem);
|
||||
MOZ_ASSERT(!listElem->isInList());
|
||||
|
||||
listElem->next = this->next;
|
||||
listElem->prev = this;
|
||||
this->next->prev = listElem;
|
||||
this->next = listElem;
|
||||
listElem->next = this->next;
|
||||
listElem->prev = this;
|
||||
this->next->prev = listElem;
|
||||
this->next = listElem;
|
||||
}
|
||||
|
||||
/*
|
||||
* Insert elem before this element, but don't check that this element is in
|
||||
* the list. This is called by LinkedList::insertBack().
|
||||
*/
|
||||
void setPreviousUnsafe(T* elem)
|
||||
{
|
||||
LinkedListElement<T>* listElem = static_cast<LinkedListElement<T>*>(elem);
|
||||
MOZ_ASSERT(!listElem->isInList());
|
||||
void setPreviousUnsafe(T* elem) {
|
||||
LinkedListElement<T>* listElem = static_cast<LinkedListElement<T>*>(elem);
|
||||
MOZ_ASSERT(!listElem->isInList());
|
||||
|
||||
listElem->next = this;
|
||||
listElem->prev = this->prev;
|
||||
this->prev->next = listElem;
|
||||
this->prev = listElem;
|
||||
listElem->next = this;
|
||||
listElem->prev = this->prev;
|
||||
this->prev->next = listElem;
|
||||
this->prev = listElem;
|
||||
}
|
||||
|
||||
private:
|
||||
LinkedListElement& operator=(const LinkedList<T>& other) MOZ_DELETE;
|
||||
LinkedListElement(const LinkedList<T>& other) MOZ_DELETE;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class LinkedList
|
||||
{
|
||||
private:
|
||||
private:
|
||||
LinkedListElement<T> sentinel;
|
||||
|
||||
public:
|
||||
LinkedList& operator=(const LinkedList<T>& other) MOZ_DELETE;
|
||||
LinkedList(const LinkedList<T>& other) MOZ_DELETE;
|
||||
|
||||
LinkedList()
|
||||
: sentinel(LinkedListElement<T>::NODE_KIND_SENTINEL)
|
||||
{
|
||||
}
|
||||
public:
|
||||
LinkedList() : sentinel(LinkedListElement<T>::NODE_KIND_SENTINEL) { }
|
||||
|
||||
/*
|
||||
* Add elem to the front of the list.
|
||||
*/
|
||||
void insertFront(T* elem)
|
||||
{
|
||||
/* Bypass setNext()'s this->isInList() assertion. */
|
||||
sentinel.setNextUnsafe(elem);
|
||||
void insertFront(T* elem) {
|
||||
/* Bypass setNext()'s this->isInList() assertion. */
|
||||
sentinel.setNextUnsafe(elem);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add elem to the back of the list.
|
||||
*/
|
||||
void insertBack(T* elem)
|
||||
{
|
||||
sentinel.setPreviousUnsafe(elem);
|
||||
void insertBack(T* elem) {
|
||||
sentinel.setPreviousUnsafe(elem);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the first element of the list, or NULL if the list is empty.
|
||||
*/
|
||||
T* getFirst()
|
||||
{
|
||||
return sentinel.getNext();
|
||||
T* getFirst() {
|
||||
return sentinel.getNext();
|
||||
}
|
||||
const T* getFirst() const {
|
||||
return sentinel.getNext();
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the last element of the list, or NULL if the list is empty.
|
||||
*/
|
||||
T* getLast()
|
||||
{
|
||||
return sentinel.getPrevious();
|
||||
T* getLast() {
|
||||
return sentinel.getPrevious();
|
||||
}
|
||||
const T* getLast() const {
|
||||
return sentinel.getPrevious();
|
||||
}
|
||||
|
||||
/*
|
||||
* Get and remove the first element of the list. If the list is empty,
|
||||
* return NULL.
|
||||
*/
|
||||
T* popFirst()
|
||||
{
|
||||
T* ret = sentinel.getNext();
|
||||
if (ret)
|
||||
static_cast<LinkedListElement<T>*>(ret)->remove();
|
||||
|
||||
return ret;
|
||||
T* popFirst() {
|
||||
T* ret = sentinel.getNext();
|
||||
if (ret)
|
||||
static_cast<LinkedListElement<T>*>(ret)->remove();
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get and remove the last element of the list. If the list is empty,
|
||||
* return NULL.
|
||||
*/
|
||||
T* popLast()
|
||||
{
|
||||
T* ret = sentinel.getPrevious();
|
||||
if (ret)
|
||||
static_cast<LinkedListElement<T>*>(ret)->remove();
|
||||
|
||||
return ret;
|
||||
T* popLast() {
|
||||
T* ret = sentinel.getPrevious();
|
||||
if (ret)
|
||||
static_cast<LinkedListElement<T>*>(ret)->remove();
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return true if the list is empty, or false otherwise.
|
||||
*/
|
||||
bool isEmpty()
|
||||
{
|
||||
return !sentinel.isInList();
|
||||
bool isEmpty() const {
|
||||
return !sentinel.isInList();
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -361,71 +310,73 @@ public:
|
|||
* This runs in time linear to the list's length, because we have to mark
|
||||
* each element as not in the list.
|
||||
*/
|
||||
void clear()
|
||||
{
|
||||
while (popFirst())
|
||||
continue;
|
||||
void clear() {
|
||||
while (popFirst())
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* In a debug build, make sure that the list is sane (no cycles, consistent
|
||||
* next/prev pointers, only one sentinel). Has no effect in release builds.
|
||||
*/
|
||||
void debugAssertIsSane()
|
||||
{
|
||||
void debugAssertIsSane() const {
|
||||
#ifdef DEBUG
|
||||
/*
|
||||
* Check for cycles in the forward singly-linked list using the
|
||||
* tortoise/hare algorithm.
|
||||
*/
|
||||
for (LinkedListElement<T>* slow = sentinel.next,
|
||||
* fast1 = sentinel.next->next,
|
||||
* fast2 = sentinel.next->next->next;
|
||||
slow != sentinel && fast1 != sentinel && fast2 != sentinel;
|
||||
slow = slow->next,
|
||||
fast1 = fast2->next,
|
||||
fast2 = fast1->next) {
|
||||
const LinkedListElement<T>* slow;
|
||||
const LinkedListElement<T>* fast1;
|
||||
const LinkedListElement<T>* fast2;
|
||||
|
||||
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. */
|
||||
for (LinkedListElement<T>* slow = sentinel.prev,
|
||||
* fast1 = sentinel.prev->prev,
|
||||
* fast2 = sentinel.prev->prev->prev;
|
||||
slow != sentinel && fast1 != sentinel && fast2 != sentinel;
|
||||
slow = slow->prev,
|
||||
fast1 = fast2->prev,
|
||||
fast2 = fast1->prev) {
|
||||
/* Check for cycles in the backward singly-linked list. */
|
||||
for (slow = sentinel.prev,
|
||||
fast1 = sentinel.prev->prev,
|
||||
fast2 = sentinel.prev->prev->prev;
|
||||
slow != sentinel && fast1 != sentinel && fast2 != sentinel;
|
||||
slow = slow->prev, fast1 = fast2->prev, fast2 = fast1->prev)
|
||||
{
|
||||
MOZ_ASSERT(slow != fast1);
|
||||
MOZ_ASSERT(slow != fast2);
|
||||
}
|
||||
|
||||
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 |sentinel| is the only node in the list with
|
||||
* isSentinel == true.
|
||||
*/
|
||||
for (LinkedListElement<T>* elem = sentinel.next;
|
||||
elem != sentinel;
|
||||
elem = elem->next) {
|
||||
/* Check that the next/prev pointers match up. */
|
||||
const LinkedListElement<T>* prev = sentinel;
|
||||
const LinkedListElement<T>* cur = sentinel.next;
|
||||
do {
|
||||
MOZ_ASSERT(cur->prev == prev);
|
||||
MOZ_ASSERT(prev->next == cur);
|
||||
|
||||
MOZ_ASSERT(!elem->isSentinel);
|
||||
}
|
||||
|
||||
/* Check that the next/prev pointers match up. */
|
||||
LinkedListElement<T>* prev = sentinel;
|
||||
LinkedListElement<T>* cur = sentinel.next;
|
||||
do {
|
||||
MOZ_ASSERT(cur->prev == prev);
|
||||
MOZ_ASSERT(prev->next == cur);
|
||||
|
||||
prev = cur;
|
||||
cur = cur->next;
|
||||
} while (cur != sentinel);
|
||||
prev = cur;
|
||||
cur = cur->next;
|
||||
} while (cur != sentinel);
|
||||
#endif /* ifdef DEBUG */
|
||||
}
|
||||
|
||||
private:
|
||||
LinkedList& operator=(const LinkedList<T>& other) MOZ_DELETE;
|
||||
LinkedList(const LinkedList<T>& other) MOZ_DELETE;
|
||||
};
|
||||
|
||||
} /* namespace mozilla */
|
||||
|
|
|
@ -1,42 +1,7 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at:
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Jeff Walden <jwalden+code@mit.edu> (original author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/* -*- 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/. */
|
||||
|
||||
/*
|
||||
* 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
|
||||
* implement bounds checking in debug builds.
|
||||
*/
|
||||
template <typename T>
|
||||
template<typename T>
|
||||
class RangedPtr
|
||||
{
|
||||
T* ptr;
|
||||
|
@ -82,16 +47,16 @@ class RangedPtr
|
|||
#endif
|
||||
|
||||
void checkSanity() {
|
||||
MOZ_ASSERT(rangeStart <= ptr);
|
||||
MOZ_ASSERT(ptr <= rangeEnd);
|
||||
MOZ_ASSERT(rangeStart <= ptr);
|
||||
MOZ_ASSERT(ptr <= rangeEnd);
|
||||
}
|
||||
|
||||
/* Creates a new pointer for |ptr|, restricted to this pointer's range. */
|
||||
RangedPtr<T> create(T *ptr) const {
|
||||
#ifdef DEBUG
|
||||
return RangedPtr<T>(ptr, rangeStart, rangeEnd);
|
||||
return RangedPtr<T>(ptr, rangeStart, rangeEnd);
|
||||
#else
|
||||
return RangedPtr<T>(ptr, NULL, size_t(0));
|
||||
return RangedPtr<T>(ptr, NULL, size_t(0));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -102,8 +67,8 @@ class RangedPtr
|
|||
, rangeStart(start), rangeEnd(end)
|
||||
#endif
|
||||
{
|
||||
MOZ_ASSERT(rangeStart <= rangeEnd);
|
||||
checkSanity();
|
||||
MOZ_ASSERT(rangeStart <= rangeEnd);
|
||||
checkSanity();
|
||||
}
|
||||
RangedPtr(T* p, T* start, size_t length)
|
||||
: ptr(p)
|
||||
|
@ -111,9 +76,9 @@ class RangedPtr
|
|||
, rangeStart(start), rangeEnd(start + length)
|
||||
#endif
|
||||
{
|
||||
MOZ_ASSERT(length <= size_t(-1) / sizeof(T));
|
||||
MOZ_ASSERT(uintptr_t(rangeStart) + length * sizeof(T) >= uintptr_t(rangeStart));
|
||||
checkSanity();
|
||||
MOZ_ASSERT(length <= size_t(-1) / sizeof(T));
|
||||
MOZ_ASSERT(uintptr_t(rangeStart) + length * sizeof(T) >= uintptr_t(rangeStart));
|
||||
checkSanity();
|
||||
}
|
||||
|
||||
/* Equivalent to RangedPtr(p, p, length). */
|
||||
|
@ -123,9 +88,9 @@ class RangedPtr
|
|||
, rangeStart(p), rangeEnd(p + length)
|
||||
#endif
|
||||
{
|
||||
MOZ_ASSERT(length <= size_t(-1) / sizeof(T));
|
||||
MOZ_ASSERT(uintptr_t(rangeStart) + length * sizeof(T) >= uintptr_t(rangeStart));
|
||||
checkSanity();
|
||||
MOZ_ASSERT(length <= size_t(-1) / sizeof(T));
|
||||
MOZ_ASSERT(uintptr_t(rangeStart) + length * sizeof(T) >= uintptr_t(rangeStart));
|
||||
checkSanity();
|
||||
}
|
||||
|
||||
/* Equivalent to RangedPtr(arr, arr, N). */
|
||||
|
@ -140,7 +105,7 @@ class RangedPtr
|
|||
}
|
||||
|
||||
T* get() const {
|
||||
return ptr;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -154,23 +119,23 @@ class RangedPtr
|
|||
* p1 = RangedPtr<char>(arr2, 3); // asserts
|
||||
*/
|
||||
RangedPtr<T>& operator=(const RangedPtr<T>& other) {
|
||||
MOZ_ASSERT(rangeStart == other.rangeStart);
|
||||
MOZ_ASSERT(rangeEnd == other.rangeEnd);
|
||||
ptr = other.ptr;
|
||||
checkSanity();
|
||||
return *this;
|
||||
MOZ_ASSERT(rangeStart == other.rangeStart);
|
||||
MOZ_ASSERT(rangeEnd == other.rangeEnd);
|
||||
ptr = other.ptr;
|
||||
checkSanity();
|
||||
return *this;
|
||||
}
|
||||
|
||||
RangedPtr<T> operator+(size_t inc) {
|
||||
MOZ_ASSERT(inc <= size_t(-1) / sizeof(T));
|
||||
MOZ_ASSERT(ptr + inc > ptr);
|
||||
return create(ptr + inc);
|
||||
MOZ_ASSERT(inc <= size_t(-1) / sizeof(T));
|
||||
MOZ_ASSERT(ptr + inc > ptr);
|
||||
return create(ptr + inc);
|
||||
}
|
||||
|
||||
RangedPtr<T> operator-(size_t dec) {
|
||||
MOZ_ASSERT(dec <= size_t(-1) / sizeof(T));
|
||||
MOZ_ASSERT(ptr - dec < ptr);
|
||||
return create(ptr - dec);
|
||||
MOZ_ASSERT(dec <= size_t(-1) / sizeof(T));
|
||||
MOZ_ASSERT(ptr - dec < ptr);
|
||||
return create(ptr - dec);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -179,97 +144,97 @@ class RangedPtr
|
|||
*/
|
||||
template <typename U>
|
||||
RangedPtr<T>& operator=(U* p) {
|
||||
*this = create(p);
|
||||
return *this;
|
||||
*this = create(p);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
RangedPtr<T>& operator=(const RangedPtr<U>& p) {
|
||||
MOZ_ASSERT(rangeStart <= p.ptr);
|
||||
MOZ_ASSERT(p.ptr <= rangeEnd);
|
||||
ptr = p.ptr;
|
||||
checkSanity();
|
||||
return *this;
|
||||
MOZ_ASSERT(rangeStart <= p.ptr);
|
||||
MOZ_ASSERT(p.ptr <= rangeEnd);
|
||||
ptr = p.ptr;
|
||||
checkSanity();
|
||||
return *this;
|
||||
}
|
||||
|
||||
RangedPtr<T>& operator++() {
|
||||
return (*this += 1);
|
||||
return (*this += 1);
|
||||
}
|
||||
|
||||
RangedPtr<T> operator++(int) {
|
||||
RangedPtr<T> rcp = *this;
|
||||
++*this;
|
||||
return rcp;
|
||||
RangedPtr<T> rcp = *this;
|
||||
++*this;
|
||||
return rcp;
|
||||
}
|
||||
|
||||
RangedPtr<T>& operator--() {
|
||||
return (*this -= 1);
|
||||
return (*this -= 1);
|
||||
}
|
||||
|
||||
RangedPtr<T> operator--(int) {
|
||||
RangedPtr<T> rcp = *this;
|
||||
--*this;
|
||||
return rcp;
|
||||
RangedPtr<T> rcp = *this;
|
||||
--*this;
|
||||
return rcp;
|
||||
}
|
||||
|
||||
RangedPtr<T>& operator+=(size_t inc) {
|
||||
this->operator=<T>(*this + inc);
|
||||
return *this;
|
||||
*this = *this + inc;
|
||||
return *this;
|
||||
}
|
||||
|
||||
RangedPtr<T>& operator-=(size_t dec) {
|
||||
this->operator=<T>(*this - dec);
|
||||
return *this;
|
||||
*this = *this - dec;
|
||||
return *this;
|
||||
}
|
||||
|
||||
T& operator[](int index) const {
|
||||
MOZ_ASSERT(size_t(index > 0 ? index : -index) <= size_t(-1) / sizeof(T));
|
||||
return *create(ptr + index);
|
||||
MOZ_ASSERT(size_t(index > 0 ? index : -index) <= size_t(-1) / sizeof(T));
|
||||
return *create(ptr + index);
|
||||
}
|
||||
|
||||
T& operator*() const {
|
||||
return *ptr;
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
bool operator==(const RangedPtr<U>& other) const {
|
||||
return ptr == other.ptr;
|
||||
return ptr == other.ptr;
|
||||
}
|
||||
template <typename U>
|
||||
bool operator!=(const RangedPtr<U>& other) const {
|
||||
return !(*this == other);
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
bool operator==(const U* u) const {
|
||||
return ptr == u;
|
||||
return ptr == u;
|
||||
}
|
||||
template<typename U>
|
||||
bool operator!=(const U* u) const {
|
||||
return !(*this == u);
|
||||
return !(*this == u);
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
bool operator<(const RangedPtr<U>& other) const {
|
||||
return ptr < other.ptr;
|
||||
return ptr < other.ptr;
|
||||
}
|
||||
template <typename U>
|
||||
bool operator<=(const RangedPtr<U>& other) const {
|
||||
return ptr <= other.ptr;
|
||||
return ptr <= other.ptr;
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
bool operator>(const RangedPtr<U>& other) const {
|
||||
return ptr > other.ptr;
|
||||
return ptr > other.ptr;
|
||||
}
|
||||
template <typename U>
|
||||
bool operator>=(const RangedPtr<U>& other) const {
|
||||
return ptr >= other.ptr;
|
||||
return ptr >= other.ptr;
|
||||
}
|
||||
|
||||
size_t operator-(const RangedPtr<T>& other) const {
|
||||
MOZ_ASSERT(ptr >= other.ptr);
|
||||
return PointerRangeSize(other.ptr, ptr);
|
||||
MOZ_ASSERT(ptr >= other.ptr);
|
||||
return PointerRangeSize(other.ptr, ptr);
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
|
@ -1,42 +1,7 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at:
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Chris Jones <jones.chris.g@gmail.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/* -*- 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/. */
|
||||
|
||||
/* Helpers for defining and using refcounted objects. */
|
||||
|
||||
|
@ -80,24 +45,24 @@ class RefCounted
|
|||
{
|
||||
friend class RefPtr<T>;
|
||||
|
||||
public:
|
||||
public:
|
||||
RefCounted() : refCnt(0) { }
|
||||
~RefCounted() { MOZ_ASSERT(refCnt == -0xdead); }
|
||||
|
||||
// Compatibility with nsRefPtr.
|
||||
void AddRef() {
|
||||
MOZ_ASSERT(refCnt >= 0);
|
||||
++refCnt;
|
||||
MOZ_ASSERT(refCnt >= 0);
|
||||
++refCnt;
|
||||
}
|
||||
|
||||
void Release() {
|
||||
MOZ_ASSERT(refCnt > 0);
|
||||
if (0 == --refCnt) {
|
||||
MOZ_ASSERT(refCnt > 0);
|
||||
if (0 == --refCnt) {
|
||||
#ifdef DEBUG
|
||||
refCnt = -0xdead;
|
||||
refCnt = -0xdead;
|
||||
#endif
|
||||
delete static_cast<T*>(this);
|
||||
}
|
||||
delete static_cast<T*>(this);
|
||||
}
|
||||
}
|
||||
|
||||
// Compatibility with wtf::RefPtr.
|
||||
|
@ -105,11 +70,11 @@ public:
|
|||
void deref() { Release(); }
|
||||
int refCount() const { return refCnt; }
|
||||
bool hasOneRef() const {
|
||||
MOZ_ASSERT(refCnt > 0);
|
||||
return refCnt == 1;
|
||||
MOZ_ASSERT(refCnt > 0);
|
||||
return refCnt == 1;
|
||||
}
|
||||
|
||||
private:
|
||||
private:
|
||||
int refCnt;
|
||||
};
|
||||
|
||||
|
@ -130,9 +95,9 @@ class RefPtr
|
|||
friend class TemporaryRef<T>;
|
||||
friend class OutParamRef<T>;
|
||||
|
||||
struct dontRef {};
|
||||
struct DontRef {};
|
||||
|
||||
public:
|
||||
public:
|
||||
RefPtr() : ptr(0) { }
|
||||
RefPtr(const RefPtr& o) : ptr(ref(o.ptr)) {}
|
||||
RefPtr(const TemporaryRef<T>& o) : ptr(o.drop()) {}
|
||||
|
@ -144,28 +109,28 @@ public:
|
|||
~RefPtr() { unref(ptr); }
|
||||
|
||||
RefPtr& operator=(const RefPtr& o) {
|
||||
assign(ref(o.ptr));
|
||||
return *this;
|
||||
assign(ref(o.ptr));
|
||||
return *this;
|
||||
}
|
||||
RefPtr& operator=(const TemporaryRef<T>& o) {
|
||||
assign(o.drop());
|
||||
return *this;
|
||||
assign(o.drop());
|
||||
return *this;
|
||||
}
|
||||
RefPtr& operator=(T* t) {
|
||||
assign(ref(t));
|
||||
return *this;
|
||||
assign(ref(t));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
RefPtr& operator=(const RefPtr<U>& o) {
|
||||
assign(ref(o.get()));
|
||||
return *this;
|
||||
assign(ref(o.get()));
|
||||
return *this;
|
||||
}
|
||||
|
||||
TemporaryRef<T> forget() {
|
||||
T* tmp = ptr;
|
||||
ptr = 0;
|
||||
return TemporaryRef<T>(tmp, dontRef());
|
||||
T* tmp = ptr;
|
||||
ptr = 0;
|
||||
return TemporaryRef<T>(tmp, DontRef());
|
||||
}
|
||||
|
||||
T* get() const { return ptr; }
|
||||
|
@ -175,25 +140,23 @@ public:
|
|||
template<typename U>
|
||||
operator TemporaryRef<U>() { return TemporaryRef<U>(ptr); }
|
||||
|
||||
private:
|
||||
private:
|
||||
void assign(T* t) {
|
||||
unref(ptr);
|
||||
ptr = t;
|
||||
unref(ptr);
|
||||
ptr = t;
|
||||
}
|
||||
|
||||
T* ptr;
|
||||
|
||||
static MOZ_ALWAYS_INLINE T* ref(T* t) {
|
||||
if (t) {
|
||||
t->AddRef();
|
||||
}
|
||||
return t;
|
||||
if (t)
|
||||
t->AddRef();
|
||||
return t;
|
||||
}
|
||||
|
||||
static MOZ_ALWAYS_INLINE void unref(T* t) {
|
||||
if (t) {
|
||||
t->Release();
|
||||
}
|
||||
if (t)
|
||||
t->Release();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -209,9 +172,9 @@ class TemporaryRef
|
|||
// To allow it to construct TemporaryRef from a bare 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(const TemporaryRef& o) : ptr(o.drop()) {}
|
||||
|
||||
|
@ -221,18 +184,18 @@ public:
|
|||
~TemporaryRef() { RefPtr<T>::unref(ptr); }
|
||||
|
||||
T* drop() const {
|
||||
T* tmp = ptr;
|
||||
ptr = 0;
|
||||
return tmp;
|
||||
T* tmp = ptr;
|
||||
ptr = 0;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
private:
|
||||
TemporaryRef(T* t, const dontRef&) : ptr(t) {}
|
||||
private:
|
||||
TemporaryRef(T* t, const DontRef&) : ptr(t) {}
|
||||
|
||||
mutable T* ptr;
|
||||
|
||||
TemporaryRef();
|
||||
TemporaryRef& operator=(const TemporaryRef&);
|
||||
TemporaryRef() MOZ_DELETE;
|
||||
void operator=(const TemporaryRef&) MOZ_DELETE;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -254,15 +217,15 @@ class OutParamRef
|
|||
{
|
||||
friend OutParamRef byRef<T>(RefPtr<T>&);
|
||||
|
||||
public:
|
||||
public:
|
||||
~OutParamRef() {
|
||||
RefPtr<T>::unref(refPtr.ptr);
|
||||
refPtr.ptr = tmp;
|
||||
RefPtr<T>::unref(refPtr.ptr);
|
||||
refPtr.ptr = tmp;
|
||||
}
|
||||
|
||||
operator T**() { return &tmp; }
|
||||
|
||||
private:
|
||||
private:
|
||||
OutParamRef(RefPtr<T>& p) : refPtr(p), tmp(p.get()) {}
|
||||
|
||||
RefPtr<T>& refPtr;
|
||||
|
@ -279,7 +242,7 @@ template<typename T>
|
|||
OutParamRef<T>
|
||||
byRef(RefPtr<T>& ptr)
|
||||
{
|
||||
return OutParamRef<T>(ptr);
|
||||
return OutParamRef<T>(ptr);
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -297,15 +260,15 @@ using namespace mozilla;
|
|||
|
||||
struct Foo : public RefCounted<Foo>
|
||||
{
|
||||
Foo() : dead(false) { }
|
||||
~Foo() {
|
||||
MOZ_ASSERT(!dead);
|
||||
dead = true;
|
||||
numDestroyed++;
|
||||
}
|
||||
Foo() : dead(false) { }
|
||||
~Foo() {
|
||||
MOZ_ASSERT(!dead);
|
||||
dead = true;
|
||||
numDestroyed++;
|
||||
}
|
||||
|
||||
bool dead;
|
||||
static int numDestroyed;
|
||||
bool dead;
|
||||
static int numDestroyed;
|
||||
};
|
||||
int Foo::numDestroyed;
|
||||
|
||||
|
@ -314,34 +277,34 @@ struct Bar : public Foo { };
|
|||
TemporaryRef<Foo>
|
||||
NewFoo()
|
||||
{
|
||||
return RefPtr<Foo>(new Foo());
|
||||
return RefPtr<Foo>(new Foo());
|
||||
}
|
||||
|
||||
TemporaryRef<Foo>
|
||||
NewBar()
|
||||
{
|
||||
return new Bar();
|
||||
return new Bar();
|
||||
}
|
||||
|
||||
void
|
||||
GetNewFoo(Foo** f)
|
||||
{
|
||||
*f = new Bar();
|
||||
// Kids, don't try this at home
|
||||
(*f)->AddRef();
|
||||
*f = new Bar();
|
||||
// Kids, don't try this at home
|
||||
(*f)->AddRef();
|
||||
}
|
||||
|
||||
void
|
||||
GetPassedFoo(Foo** f)
|
||||
{
|
||||
// Kids, don't try this at home
|
||||
(*f)->AddRef();
|
||||
// Kids, don't try this at home
|
||||
(*f)->AddRef();
|
||||
}
|
||||
|
||||
void
|
||||
GetNewFoo(RefPtr<Foo>* f)
|
||||
{
|
||||
*f = new Bar();
|
||||
*f = new Bar();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -351,93 +314,93 @@ GetPassedFoo(RefPtr<Foo>* f)
|
|||
TemporaryRef<Foo>
|
||||
GetNullFoo()
|
||||
{
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char** argv)
|
||||
{
|
||||
// This should blow up
|
||||
// This should blow up
|
||||
// Foo* f = new Foo(); delete f;
|
||||
|
||||
MOZ_ASSERT(0 == Foo::numDestroyed);
|
||||
{
|
||||
RefPtr<Foo> f = new Foo();
|
||||
MOZ_ASSERT(f->refCount() == 1);
|
||||
}
|
||||
MOZ_ASSERT(0 == Foo::numDestroyed);
|
||||
{
|
||||
RefPtr<Foo> f = new Foo();
|
||||
MOZ_ASSERT(f->refCount() == 1);
|
||||
}
|
||||
MOZ_ASSERT(1 == Foo::numDestroyed);
|
||||
|
||||
{
|
||||
RefPtr<Foo> f1 = NewFoo();
|
||||
RefPtr<Foo> f2(NewFoo());
|
||||
MOZ_ASSERT(1 == Foo::numDestroyed);
|
||||
}
|
||||
MOZ_ASSERT(3 == Foo::numDestroyed);
|
||||
|
||||
{
|
||||
RefPtr<Foo> f1 = NewFoo();
|
||||
RefPtr<Foo> f2(NewFoo());
|
||||
MOZ_ASSERT(1 == Foo::numDestroyed);
|
||||
}
|
||||
{
|
||||
RefPtr<Foo> b = NewBar();
|
||||
MOZ_ASSERT(3 == Foo::numDestroyed);
|
||||
}
|
||||
MOZ_ASSERT(4 == Foo::numDestroyed);
|
||||
|
||||
{
|
||||
RefPtr<Foo> f1;
|
||||
{
|
||||
RefPtr<Foo> b = NewBar();
|
||||
MOZ_ASSERT(3 == Foo::numDestroyed);
|
||||
f1 = new Foo();
|
||||
RefPtr<Foo> f2(f1);
|
||||
RefPtr<Foo> f3 = f2;
|
||||
MOZ_ASSERT(4 == Foo::numDestroyed);
|
||||
}
|
||||
MOZ_ASSERT(4 == Foo::numDestroyed);
|
||||
}
|
||||
MOZ_ASSERT(5 == Foo::numDestroyed);
|
||||
|
||||
{
|
||||
RefPtr<Foo> f1;
|
||||
{
|
||||
f1 = new Foo();
|
||||
RefPtr<Foo> f2(f1);
|
||||
RefPtr<Foo> f3 = f2;
|
||||
MOZ_ASSERT(4 == Foo::numDestroyed);
|
||||
}
|
||||
MOZ_ASSERT(4 == Foo::numDestroyed);
|
||||
}
|
||||
MOZ_ASSERT(5 == Foo::numDestroyed);
|
||||
{
|
||||
RefPtr<Foo> f = new Foo();
|
||||
f.forget();
|
||||
MOZ_ASSERT(6 == Foo::numDestroyed);
|
||||
}
|
||||
|
||||
{
|
||||
RefPtr<Foo> f = new Foo();
|
||||
f.forget();
|
||||
MOZ_ASSERT(6 == Foo::numDestroyed);
|
||||
}
|
||||
{
|
||||
RefPtr<Foo> f = new Foo();
|
||||
GetNewFoo(byRef(f));
|
||||
MOZ_ASSERT(7 == Foo::numDestroyed);
|
||||
}
|
||||
MOZ_ASSERT(8 == Foo::numDestroyed);
|
||||
|
||||
{
|
||||
RefPtr<Foo> f = new Foo();
|
||||
GetNewFoo(byRef(f));
|
||||
MOZ_ASSERT(7 == Foo::numDestroyed);
|
||||
}
|
||||
{
|
||||
RefPtr<Foo> f = new Foo();
|
||||
GetPassedFoo(byRef(f));
|
||||
MOZ_ASSERT(8 == Foo::numDestroyed);
|
||||
}
|
||||
MOZ_ASSERT(9 == Foo::numDestroyed);
|
||||
|
||||
{
|
||||
RefPtr<Foo> f = new Foo();
|
||||
GetPassedFoo(byRef(f));
|
||||
MOZ_ASSERT(8 == Foo::numDestroyed);
|
||||
}
|
||||
MOZ_ASSERT(9 == Foo::numDestroyed);
|
||||
{
|
||||
RefPtr<Foo> f = new Foo();
|
||||
GetNewFoo(&f);
|
||||
MOZ_ASSERT(10 == Foo::numDestroyed);
|
||||
}
|
||||
MOZ_ASSERT(11 == Foo::numDestroyed);
|
||||
|
||||
{
|
||||
RefPtr<Foo> f = new Foo();
|
||||
GetNewFoo(&f);
|
||||
MOZ_ASSERT(10 == Foo::numDestroyed);
|
||||
}
|
||||
{
|
||||
RefPtr<Foo> f = new Foo();
|
||||
GetPassedFoo(&f);
|
||||
MOZ_ASSERT(11 == Foo::numDestroyed);
|
||||
}
|
||||
MOZ_ASSERT(12 == Foo::numDestroyed);
|
||||
|
||||
{
|
||||
RefPtr<Foo> f = new Foo();
|
||||
GetPassedFoo(&f);
|
||||
MOZ_ASSERT(11 == Foo::numDestroyed);
|
||||
}
|
||||
MOZ_ASSERT(12 == Foo::numDestroyed);
|
||||
{
|
||||
RefPtr<Foo> f1 = new Bar();
|
||||
}
|
||||
MOZ_ASSERT(13 == Foo::numDestroyed);
|
||||
|
||||
{
|
||||
RefPtr<Foo> f1 = new Bar();
|
||||
}
|
||||
{
|
||||
RefPtr<Foo> f = GetNullFoo();
|
||||
MOZ_ASSERT(13 == Foo::numDestroyed);
|
||||
}
|
||||
MOZ_ASSERT(13 == Foo::numDestroyed);
|
||||
|
||||
{
|
||||
RefPtr<Foo> f = GetNullFoo();
|
||||
MOZ_ASSERT(13 == Foo::numDestroyed);
|
||||
}
|
||||
MOZ_ASSERT(13 == Foo::numDestroyed);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -35,12 +35,12 @@
|
|||
* Note that the RAII classes defined in this header do _not_ perform any form
|
||||
* of reference-counting or garbage-collection. These classes have exactly two
|
||||
* behaviors:
|
||||
*
|
||||
* - if |forget()| has not been called, the resource is always deallocated at
|
||||
* the end of the scope;
|
||||
* - if |forget()| has been called, any control on the resource is unbound
|
||||
* and the resource is not deallocated by the class.
|
||||
*
|
||||
*
|
||||
* Extension:
|
||||
*
|
||||
* In addition, this header provides class |Scoped| and macro |SCOPED_TEMPLATE|
|
||||
|
@ -52,6 +52,8 @@
|
|||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/GuardObjects.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
/*
|
||||
* Scoped is a helper to create RAII wrappers
|
||||
* Type argument |Traits| is expected to have the following structure:
|
||||
|
@ -66,87 +68,87 @@
|
|||
* const static void release(type);
|
||||
* }
|
||||
*/
|
||||
template <typename Traits>
|
||||
template<typename Traits>
|
||||
class Scoped
|
||||
{
|
||||
public:
|
||||
typedef typename Traits::type Resource;
|
||||
public:
|
||||
typedef typename Traits::type Resource;
|
||||
|
||||
explicit Scoped(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM)
|
||||
: value(Traits::empty())
|
||||
{
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
}
|
||||
explicit Scoped(const Resource& value
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
: value(value)
|
||||
{
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
}
|
||||
~Scoped() {
|
||||
Traits::release(value);
|
||||
}
|
||||
explicit Scoped(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM)
|
||||
: value(Traits::empty())
|
||||
{
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
}
|
||||
explicit Scoped(const Resource& value
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
: value(value)
|
||||
{
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
}
|
||||
~Scoped() {
|
||||
Traits::release(value);
|
||||
}
|
||||
|
||||
// Constant getter
|
||||
operator const Resource&() const { return value; }
|
||||
const Resource& operator->() const { return value; }
|
||||
const Resource& get() const { return value; }
|
||||
// Non-constant getter.
|
||||
Resource& rwget() { return value; }
|
||||
// Constant getter
|
||||
operator const Resource&() const { return value; }
|
||||
const Resource& operator->() const { return value; }
|
||||
const Resource& get() const { return value; }
|
||||
// Non-constant getter.
|
||||
Resource& rwget() { return value; }
|
||||
|
||||
/*
|
||||
* Forget the resource.
|
||||
*
|
||||
* Once |forget| has been called, the |Scoped| is neutralized, i.e. it will
|
||||
* have no effect at destruction (unless it is reset to another resource by
|
||||
* |operator=|).
|
||||
*
|
||||
* @return The original resource.
|
||||
*/
|
||||
Resource forget() {
|
||||
Resource tmp = value;
|
||||
value = Traits::empty();
|
||||
return tmp;
|
||||
}
|
||||
/*
|
||||
* Forget the resource.
|
||||
*
|
||||
* Once |forget| has been called, the |Scoped| is neutralized, i.e. it will
|
||||
* have no effect at destruction (unless it is reset to another resource by
|
||||
* |operator=|).
|
||||
*
|
||||
* @return The original resource.
|
||||
*/
|
||||
Resource forget() {
|
||||
Resource tmp = value;
|
||||
value = Traits::empty();
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform immediate clean-up of this |Scoped|.
|
||||
*
|
||||
* If this |Scoped| is currently empty, this method has no effect.
|
||||
*/
|
||||
void dispose() {
|
||||
Traits::release(value);
|
||||
value = Traits::empty();
|
||||
}
|
||||
/*
|
||||
* Perform immediate clean-up of this |Scoped|.
|
||||
*
|
||||
* If this |Scoped| is currently empty, this method has no effect.
|
||||
*/
|
||||
void dispose() {
|
||||
Traits::release(value);
|
||||
value = Traits::empty();
|
||||
}
|
||||
|
||||
bool operator==(const Resource& other) const {
|
||||
return value == other;
|
||||
}
|
||||
bool operator==(const Resource& other) const {
|
||||
return value == other;
|
||||
}
|
||||
|
||||
/*
|
||||
* Replace the resource with another resource.
|
||||
*
|
||||
* Calling |operator=| has the side-effect of triggering clean-up. If you do
|
||||
* not want to trigger clean-up, you should first invoke |forget|.
|
||||
*
|
||||
* @return this
|
||||
*/
|
||||
Scoped<Traits>& operator=(const Resource& other) {
|
||||
return reset(other);
|
||||
}
|
||||
Scoped<Traits>& reset(const Resource& other) {
|
||||
Traits::release(value);
|
||||
value = other;
|
||||
return *this;
|
||||
}
|
||||
/*
|
||||
* Replace the resource with another resource.
|
||||
*
|
||||
* Calling |operator=| has the side-effect of triggering clean-up. If you do
|
||||
* not want to trigger clean-up, you should first invoke |forget|.
|
||||
*
|
||||
* @return this
|
||||
*/
|
||||
Scoped<Traits>& operator=(const Resource& other) {
|
||||
return reset(other);
|
||||
}
|
||||
Scoped<Traits>& reset(const Resource& other) {
|
||||
Traits::release(value);
|
||||
value = other;
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
explicit Scoped(const Scoped<Traits>& value) MOZ_DELETE;
|
||||
Scoped<Traits>& operator=(const Scoped<Traits>& value) MOZ_DELETE;
|
||||
private:
|
||||
explicit Scoped(const Scoped<Traits>& value) MOZ_DELETE;
|
||||
Scoped<Traits>& operator=(const Scoped<Traits>& value) MOZ_DELETE;
|
||||
|
||||
private:
|
||||
Resource value;
|
||||
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||
private:
|
||||
Resource value;
|
||||
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -158,25 +160,25 @@ private:
|
|||
* for more details.
|
||||
*/
|
||||
#define SCOPED_TEMPLATE(name, Traits) \
|
||||
template <typename Type> \
|
||||
struct name : public Scoped<Traits<Type> > \
|
||||
template<typename Type> \
|
||||
struct name : public mozilla::Scoped<Traits<Type> > \
|
||||
{ \
|
||||
typedef Scoped<Traits<Type> > Super; \
|
||||
typedef typename Super::Resource Resource; \
|
||||
name& operator=(Resource ptr) { \
|
||||
Super::operator=(ptr); \
|
||||
return *this; \
|
||||
} \
|
||||
explicit name(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM) \
|
||||
: Super(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_TO_PARENT) \
|
||||
{} \
|
||||
explicit name(Resource ptr \
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_PARAM) \
|
||||
: Super(ptr MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT) \
|
||||
{} \
|
||||
private: \
|
||||
explicit name(name& source) MOZ_DELETE; \
|
||||
name& operator=(name& source) MOZ_DELETE; \
|
||||
typedef mozilla::Scoped<Traits<Type> > Super; \
|
||||
typedef typename Super::Resource Resource; \
|
||||
name& operator=(Resource ptr) { \
|
||||
Super::operator=(ptr); \
|
||||
return *this; \
|
||||
} \
|
||||
explicit name(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM) \
|
||||
: Super(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_TO_PARENT) \
|
||||
{} \
|
||||
explicit name(Resource ptr \
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_PARAM) \
|
||||
: Super(ptr MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT) \
|
||||
{} \
|
||||
private: \
|
||||
explicit name(name& source) MOZ_DELETE; \
|
||||
name& operator=(name& source) MOZ_DELETE; \
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -186,12 +188,12 @@ private: \
|
|||
* ScopedFreePtr<S> foo = malloc(sizeof(S));
|
||||
* ScopedFreePtr<char> bar = strdup(str);
|
||||
*/
|
||||
template <typename T>
|
||||
template<typename T>
|
||||
struct ScopedFreePtrTraits
|
||||
{
|
||||
typedef T* type;
|
||||
static T* empty() { return NULL; }
|
||||
static void release(T* ptr) { free(ptr); }
|
||||
typedef T* type;
|
||||
static T* empty() { return NULL; }
|
||||
static void release(T* ptr) { free(ptr); }
|
||||
};
|
||||
SCOPED_TEMPLATE(ScopedFreePtr, ScopedFreePtrTraits)
|
||||
|
||||
|
@ -201,9 +203,10 @@ SCOPED_TEMPLATE(ScopedFreePtr, ScopedFreePtrTraits)
|
|||
* struct S { ... };
|
||||
* ScopedDeletePtr<S> foo = new S();
|
||||
*/
|
||||
template <typename T>
|
||||
struct ScopedDeletePtrTraits : public ScopedFreePtrTraits<T> {
|
||||
static void release(T* ptr) { delete ptr; }
|
||||
template<typename T>
|
||||
struct ScopedDeletePtrTraits : public ScopedFreePtrTraits<T>
|
||||
{
|
||||
static void release(T* ptr) { delete ptr; }
|
||||
};
|
||||
SCOPED_TEMPLATE(ScopedDeletePtr, ScopedDeletePtrTraits)
|
||||
|
||||
|
@ -213,12 +216,13 @@ SCOPED_TEMPLATE(ScopedDeletePtr, ScopedDeletePtrTraits)
|
|||
* struct S { ... };
|
||||
* ScopedDeleteArray<S> foo = new S[42];
|
||||
*/
|
||||
template <typename T>
|
||||
template<typename T>
|
||||
struct ScopedDeleteArrayTraits : public ScopedFreePtrTraits<T>
|
||||
{
|
||||
static void release(T* ptr) { delete [] ptr; }
|
||||
static void release(T* ptr) { delete [] ptr; }
|
||||
};
|
||||
SCOPED_TEMPLATE(ScopedDeleteArray, ScopedDeleteArrayTraits)
|
||||
|
||||
} /* namespace mozilla */
|
||||
|
||||
#endif // mozilla_Scoped_h_
|
||||
|
|
|
@ -1,42 +1,7 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at:
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Jeff Walden <jwalden+code@mit.edu> (original author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/* -*- 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/. */
|
||||
|
||||
/* 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 -*-
|
||||
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at:
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/* -*- 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/. */
|
||||
|
||||
/* mfbt foundational types and macros. */
|
||||
|
||||
|
|
|
@ -1,41 +1,7 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at:
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/* -*- 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/. */
|
||||
|
||||
/*
|
||||
* Miscellaneous uncategorized functionality. Please add new functionality to
|
||||
|
@ -54,54 +20,53 @@
|
|||
namespace mozilla {
|
||||
|
||||
/**
|
||||
* DebugOnly contains a value of type T, but only in debug builds. In
|
||||
* release builds, it does not contain a value. This helper is
|
||||
* intended to be used along with ASSERT()-style macros, allowing one
|
||||
* to write
|
||||
* DebugOnly contains a value of type T, but only in debug builds. In release
|
||||
* builds, it does not contain a value. This helper is intended to be used with
|
||||
* MOZ_ASSERT()-style macros, allowing one to write:
|
||||
*
|
||||
* DebugOnly<bool> check = Func();
|
||||
* ASSERT(check);
|
||||
* DebugOnly<bool> check = func();
|
||||
* MOZ_ASSERT(check);
|
||||
*
|
||||
* more concisely than declaring |check| conditional on #ifdef DEBUG,
|
||||
* but also without allocating storage space for |check| in release
|
||||
* builds.
|
||||
* more concisely than declaring |check| conditional on #ifdef DEBUG, but also
|
||||
* without allocating storage space for |check| in release builds.
|
||||
*
|
||||
* DebugOnly instances can only be coerced to T in debug builds; in
|
||||
* release builds, they don't have a value so type coercion is not
|
||||
* well defined.
|
||||
* DebugOnly instances can only be coerced to T in debug builds. In release
|
||||
* builds they don't have a value, so type coercion is not well defined.
|
||||
*/
|
||||
template <typename T>
|
||||
template<typename T>
|
||||
struct DebugOnly
|
||||
{
|
||||
#ifdef DEBUG
|
||||
T value;
|
||||
|
||||
DebugOnly() {}
|
||||
DebugOnly(const T& other) : value(other) {}
|
||||
DebugOnly(const DebugOnly& other) : value(other.value) {}
|
||||
DebugOnly() { }
|
||||
DebugOnly(const T& other) : value(other) { }
|
||||
DebugOnly(const DebugOnly& other) : value(other.value) { }
|
||||
DebugOnly& operator=(const T& rhs) {
|
||||
value = rhs;
|
||||
return *this;
|
||||
value = rhs;
|
||||
return *this;
|
||||
}
|
||||
void operator++(int) {
|
||||
value++;
|
||||
value++;
|
||||
}
|
||||
void operator--(int) {
|
||||
value--;
|
||||
value--;
|
||||
}
|
||||
|
||||
T *operator&() { return &value; }
|
||||
|
||||
operator T&() { return value; }
|
||||
operator const T&() const { return value; }
|
||||
|
||||
T& operator->() { return value; }
|
||||
|
||||
#else
|
||||
DebugOnly() {}
|
||||
DebugOnly(const T&) {}
|
||||
DebugOnly(const DebugOnly&) {}
|
||||
DebugOnly() { }
|
||||
DebugOnly(const T&) { }
|
||||
DebugOnly(const DebugOnly&) { }
|
||||
DebugOnly& operator=(const T&) { return *this; }
|
||||
void operator++(int) {}
|
||||
void operator--(int) {}
|
||||
void operator++(int) { }
|
||||
void operator--(int) { }
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@ -117,17 +82,16 @@ struct DebugOnly
|
|||
* bytes of alignment a given type needs.
|
||||
*/
|
||||
template<class T>
|
||||
struct AlignmentFinder
|
||||
class AlignmentFinder
|
||||
{
|
||||
private:
|
||||
struct Aligner
|
||||
{
|
||||
char c;
|
||||
T t;
|
||||
};
|
||||
struct Aligner
|
||||
{
|
||||
char c;
|
||||
T t;
|
||||
};
|
||||
|
||||
public:
|
||||
static const int alignment = sizeof(Aligner) - sizeof(T);
|
||||
public:
|
||||
static const size_t alignment = sizeof(Aligner) - sizeof(T);
|
||||
};
|
||||
|
||||
#define MOZ_ALIGNOF(T) mozilla::AlignmentFinder<T>::alignment
|
||||
|
@ -154,7 +118,8 @@ public:
|
|||
#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.
|
||||
*/
|
||||
|
@ -169,31 +134,31 @@ struct AlignedElem;
|
|||
template<>
|
||||
struct AlignedElem<1>
|
||||
{
|
||||
MOZ_ALIGNED_DECL(uint8_t elem, 1);
|
||||
MOZ_ALIGNED_DECL(uint8_t elem, 1);
|
||||
};
|
||||
|
||||
template<>
|
||||
struct AlignedElem<2>
|
||||
{
|
||||
MOZ_ALIGNED_DECL(uint8_t elem, 2);
|
||||
MOZ_ALIGNED_DECL(uint8_t elem, 2);
|
||||
};
|
||||
|
||||
template<>
|
||||
struct AlignedElem<4>
|
||||
{
|
||||
MOZ_ALIGNED_DECL(uint8_t elem, 4);
|
||||
MOZ_ALIGNED_DECL(uint8_t elem, 4);
|
||||
};
|
||||
|
||||
template<>
|
||||
struct AlignedElem<8>
|
||||
{
|
||||
MOZ_ALIGNED_DECL(uint8_t elem, 8);
|
||||
MOZ_ALIGNED_DECL(uint8_t elem, 8);
|
||||
};
|
||||
|
||||
template<>
|
||||
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
|
||||
* constructed using the bytes.
|
||||
*/
|
||||
template <size_t nbytes>
|
||||
template<size_t nbytes>
|
||||
struct AlignedStorage
|
||||
{
|
||||
union U {
|
||||
char bytes[nbytes];
|
||||
uint64_t _;
|
||||
char bytes[nbytes];
|
||||
uint64_t _;
|
||||
} u;
|
||||
|
||||
const void *addr() const { return u.bytes; }
|
||||
void *addr() { return u.bytes; }
|
||||
const void* addr() const { return u.bytes; }
|
||||
void* addr() { return u.bytes; }
|
||||
};
|
||||
|
||||
template <class T>
|
||||
template<class T>
|
||||
struct AlignedStorage2
|
||||
{
|
||||
union U {
|
||||
char bytes[sizeof(T)];
|
||||
uint64_t _;
|
||||
char bytes[sizeof(T)];
|
||||
uint64_t _;
|
||||
} u;
|
||||
|
||||
const T *addr() const { return (const T *)u.bytes; }
|
||||
T *addr() { return (T *)(void *)u.bytes; }
|
||||
const T* addr() const { return reinterpret_cast<const T*>(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
|
||||
* branches/loads/stores. Use with caution on hot paths.
|
||||
*/
|
||||
template <class T>
|
||||
template<class T>
|
||||
class Maybe
|
||||
{
|
||||
AlignedStorage2<T> storage;
|
||||
bool constructed;
|
||||
|
||||
T &asT() { return *storage.addr(); }
|
||||
|
||||
explicit Maybe(const Maybe &other);
|
||||
const Maybe &operator=(const Maybe &other);
|
||||
T& asT() { return *storage.addr(); }
|
||||
|
||||
public:
|
||||
Maybe() { constructed = false; }
|
||||
|
@ -259,63 +221,67 @@ class Maybe
|
|||
bool empty() const { return !constructed; }
|
||||
|
||||
void construct() {
|
||||
MOZ_ASSERT(!constructed);
|
||||
new(storage.addr()) T();
|
||||
constructed = true;
|
||||
MOZ_ASSERT(!constructed);
|
||||
new (storage.addr()) T();
|
||||
constructed = true;
|
||||
}
|
||||
|
||||
template <class T1>
|
||||
void construct(const T1 &t1) {
|
||||
MOZ_ASSERT(!constructed);
|
||||
new(storage.addr()) T(t1);
|
||||
constructed = true;
|
||||
template<class T1>
|
||||
void construct(const T1& t1) {
|
||||
MOZ_ASSERT(!constructed);
|
||||
new (storage.addr()) T(t1);
|
||||
constructed = true;
|
||||
}
|
||||
|
||||
template <class T1, class T2>
|
||||
void construct(const T1 &t1, const T2 &t2) {
|
||||
MOZ_ASSERT(!constructed);
|
||||
new(storage.addr()) T(t1, t2);
|
||||
constructed = true;
|
||||
template<class T1, class T2>
|
||||
void construct(const T1& t1, const T2& t2) {
|
||||
MOZ_ASSERT(!constructed);
|
||||
new (storage.addr()) T(t1, t2);
|
||||
constructed = true;
|
||||
}
|
||||
|
||||
template <class T1, class T2, class T3>
|
||||
void construct(const T1 &t1, const T2 &t2, const T3 &t3) {
|
||||
MOZ_ASSERT(!constructed);
|
||||
new(storage.addr()) T(t1, t2, t3);
|
||||
constructed = true;
|
||||
template<class T1, class T2, class T3>
|
||||
void construct(const T1& t1, const T2& t2, const T3& t3) {
|
||||
MOZ_ASSERT(!constructed);
|
||||
new (storage.addr()) T(t1, t2, t3);
|
||||
constructed = true;
|
||||
}
|
||||
|
||||
template <class T1, class T2, class T3, class T4>
|
||||
void construct(const T1 &t1, const T2 &t2, const T3 &t3, const T4 &t4) {
|
||||
MOZ_ASSERT(!constructed);
|
||||
new(storage.addr()) T(t1, t2, t3, t4);
|
||||
constructed = true;
|
||||
template<class T1, class T2, class T3, class T4>
|
||||
void construct(const T1& t1, const T2& t2, const T3& t3, const T4& t4) {
|
||||
MOZ_ASSERT(!constructed);
|
||||
new (storage.addr()) T(t1, t2, t3, t4);
|
||||
constructed = true;
|
||||
}
|
||||
|
||||
T *addr() {
|
||||
MOZ_ASSERT(constructed);
|
||||
return &asT();
|
||||
T* addr() {
|
||||
MOZ_ASSERT(constructed);
|
||||
return &asT();
|
||||
}
|
||||
|
||||
T &ref() {
|
||||
MOZ_ASSERT(constructed);
|
||||
return asT();
|
||||
T& ref() {
|
||||
MOZ_ASSERT(constructed);
|
||||
return asT();
|
||||
}
|
||||
|
||||
const T &ref() const {
|
||||
MOZ_ASSERT(constructed);
|
||||
return const_cast<Maybe *>(this)->asT();
|
||||
const T& ref() const {
|
||||
MOZ_ASSERT(constructed);
|
||||
return const_cast<Maybe*>(this)->asT();
|
||||
}
|
||||
|
||||
void destroy() {
|
||||
ref().~T();
|
||||
constructed = false;
|
||||
ref().~T();
|
||||
constructed = false;
|
||||
}
|
||||
|
||||
void destroyIfConstructed() {
|
||||
if (!empty())
|
||||
destroy();
|
||||
if (!empty())
|
||||
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
|
||||
* size_t(-1), instead of the real difference.
|
||||
*/
|
||||
template <class T>
|
||||
template<class T>
|
||||
MOZ_ALWAYS_INLINE size_t
|
||||
PointerRangeSize(T* begin, T* end)
|
||||
{
|
||||
MOZ_ASSERT(end >= begin);
|
||||
return (size_t(end) - size_t(begin)) / sizeof(T);
|
||||
MOZ_ASSERT(end >= begin);
|
||||
return (size_t(end) - size_t(begin)) / sizeof(T);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -342,7 +308,7 @@ template<typename T, size_t N>
|
|||
size_t
|
||||
ArrayLength(T (&arr)[N])
|
||||
{
|
||||
return N;
|
||||
return N;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -354,7 +320,7 @@ template<typename T, size_t N>
|
|||
T*
|
||||
ArrayEnd(T (&arr)[N])
|
||||
{
|
||||
return arr + ArrayLength(arr);
|
||||
return arr + ArrayLength(arr);
|
||||
}
|
||||
|
||||
} /* namespace mozilla */
|
||||
|
|
|
@ -1 +1 @@
|
|||
b55240db62f4497ae539c524d8a5ed2efb2a6b48
|
||||
4b6a92efb0e694d8aee845c9c7fcd1c2e63adab6
|
Loading…
Reference in New Issue