mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 684526 - Unify jsval and js::Value (r=jorendorff)
--HG-- extra : rebase_source : 5655602775d575bb5adba0a8fc4c20621f393a67
This commit is contained in:
parent
5a81c92645
commit
cc2ce861d1
@ -1361,8 +1361,8 @@ protected:
|
||||
can forward all the document stuff to this implementation.
|
||||
*/
|
||||
#define EVENT(name_, id_, type_, struct_) \
|
||||
NS_IMETHOD GetOn##name_(JSContext *cx, jsval *vp); \
|
||||
NS_IMETHOD SetOn##name_(JSContext *cx, const jsval &v);
|
||||
NS_IMETHOD GetOn##name_(JSContext *cx, JS::Value *vp); \
|
||||
NS_IMETHOD SetOn##name_(JSContext *cx, const JS::Value &v);
|
||||
#define TOUCH_EVENT EVENT
|
||||
#define DOCUMENT_ONLY_EVENT EVENT
|
||||
#include "nsEventNameList.h"
|
||||
|
@ -42,6 +42,7 @@
|
||||
#include "nsIDOMMessageEvent.h"
|
||||
#include "nsDOMEvent.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "jsapi.h"
|
||||
|
||||
/**
|
||||
* Implements the MessageEvent event, used for cross-document messaging and
|
||||
|
@ -41,7 +41,7 @@
|
||||
|
||||
#include "Workers.h"
|
||||
|
||||
#include "jspubtd.h"
|
||||
#include "jsapi.h"
|
||||
#include "prclist.h"
|
||||
|
||||
BEGIN_WORKERS_NAMESPACE
|
||||
|
@ -41,7 +41,7 @@
|
||||
|
||||
#include "Workers.h"
|
||||
|
||||
#include "jspubtd.h"
|
||||
#include "jsapi.h"
|
||||
|
||||
BEGIN_WORKERS_NAMESPACE
|
||||
|
||||
|
@ -41,7 +41,7 @@
|
||||
|
||||
#include "Workers.h"
|
||||
|
||||
#include "jspubtd.h"
|
||||
#include "jsapi.h"
|
||||
|
||||
BEGIN_WORKERS_NAMESPACE
|
||||
|
||||
|
@ -115,7 +115,7 @@ TestShellCommandParent::SetCallback(JSContext* aCx,
|
||||
JSBool
|
||||
TestShellCommandParent::RunCallback(const nsString& aResponse)
|
||||
{
|
||||
NS_ENSURE_TRUE(mCallback != JSVAL_NULL && mCx, JS_FALSE);
|
||||
NS_ENSURE_TRUE(*mCallback.ToJSValPtr() != JSVAL_NULL && mCx, JS_FALSE);
|
||||
|
||||
JSAutoRequest ar(mCx);
|
||||
|
||||
|
@ -167,20 +167,18 @@ class AutoVersionAPI
|
||||
#define JS_ADDRESSOF_VA_LIST(ap) (&(ap))
|
||||
#endif
|
||||
|
||||
#ifdef JS_USE_JSVAL_JSID_STRUCT_TYPES
|
||||
JS_PUBLIC_DATA(jsid) JS_DEFAULT_XML_NAMESPACE_ID = { size_t(JSID_TYPE_DEFAULT_XML_NAMESPACE) };
|
||||
JS_PUBLIC_DATA(jsid) JSID_VOID = { size_t(JSID_TYPE_VOID) };
|
||||
JS_PUBLIC_DATA(jsid) JSID_EMPTY = { size_t(JSID_TYPE_OBJECT) };
|
||||
#ifdef JS_USE_JSID_STRUCT_TYPES
|
||||
jsid JS_DEFAULT_XML_NAMESPACE_ID = { size_t(JSID_TYPE_DEFAULT_XML_NAMESPACE) };
|
||||
jsid JSID_VOID = { size_t(JSID_TYPE_VOID) };
|
||||
jsid JSID_EMPTY = { size_t(JSID_TYPE_OBJECT) };
|
||||
#endif
|
||||
|
||||
#ifdef JS_USE_JSVAL_JSID_STRUCT_TYPES
|
||||
JS_PUBLIC_DATA(jsval) JSVAL_NULL = { BUILD_JSVAL(JSVAL_TAG_NULL, 0) };
|
||||
JS_PUBLIC_DATA(jsval) JSVAL_ZERO = { BUILD_JSVAL(JSVAL_TAG_INT32, 0) };
|
||||
JS_PUBLIC_DATA(jsval) JSVAL_ONE = { BUILD_JSVAL(JSVAL_TAG_INT32, 1) };
|
||||
JS_PUBLIC_DATA(jsval) JSVAL_FALSE = { BUILD_JSVAL(JSVAL_TAG_BOOLEAN, JS_FALSE) };
|
||||
JS_PUBLIC_DATA(jsval) JSVAL_TRUE = { BUILD_JSVAL(JSVAL_TAG_BOOLEAN, JS_TRUE) };
|
||||
JS_PUBLIC_DATA(jsval) JSVAL_VOID = { BUILD_JSVAL(JSVAL_TAG_UNDEFINED, 0) };
|
||||
#endif
|
||||
const jsval JSVAL_NULL = IMPL_TO_JSVAL(BUILD_JSVAL(JSVAL_TAG_NULL, 0));
|
||||
const jsval JSVAL_ZERO = IMPL_TO_JSVAL(BUILD_JSVAL(JSVAL_TAG_INT32, 0));
|
||||
const jsval JSVAL_ONE = IMPL_TO_JSVAL(BUILD_JSVAL(JSVAL_TAG_INT32, 1));
|
||||
const jsval JSVAL_FALSE = IMPL_TO_JSVAL(BUILD_JSVAL(JSVAL_TAG_BOOLEAN, JS_FALSE));
|
||||
const jsval JSVAL_TRUE = IMPL_TO_JSVAL(BUILD_JSVAL(JSVAL_TAG_BOOLEAN, JS_TRUE));
|
||||
const jsval JSVAL_VOID = IMPL_TO_JSVAL(BUILD_JSVAL(JSVAL_TAG_UNDEFINED, 0));
|
||||
|
||||
/* Make sure that jschar is two bytes unsigned integer */
|
||||
JS_STATIC_ASSERT((jschar)-1 > 0);
|
||||
|
1537
js/src/jsapi.h
1537
js/src/jsapi.h
File diff suppressed because it is too large
Load Diff
@ -70,7 +70,7 @@ JSObject::ensureDenseArrayInitializedLength(JSContext *cx, uint32 index, uint32
|
||||
JS_ASSERT(index + extra <= capacity);
|
||||
if (initializedLength < index) {
|
||||
markDenseArrayNotPacked(cx);
|
||||
ClearValueRange(slots + initializedLength, index - initializedLength, true);
|
||||
js::ClearValueRange(slots + initializedLength, index - initializedLength, true);
|
||||
}
|
||||
if (initializedLength < index + extra)
|
||||
initializedLength = index + extra;
|
||||
|
@ -605,7 +605,7 @@ JSStructuredCloneReader::checkDouble(jsdouble d)
|
||||
{
|
||||
jsval_layout l;
|
||||
l.asDouble = d;
|
||||
if (!JSVAL_IS_DOUBLE(JSVAL_FROM_LAYOUT(l))) {
|
||||
if (!JSVAL_IS_DOUBLE_IMPL(l)) {
|
||||
JS_ReportErrorNumber(context(), js_GetErrorMessage, NULL,
|
||||
JSMSG_SC_BAD_SERIALIZED_DATA, "unrecognized NaN");
|
||||
return false;
|
||||
|
@ -1519,13 +1519,6 @@ class AutoValueRooter : private AutoGCRooter
|
||||
JS_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
}
|
||||
|
||||
AutoValueRooter(JSContext *cx, jsval v
|
||||
JS_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
: AutoGCRooter(cx, JSVAL), val(js::Valueify(v))
|
||||
{
|
||||
JS_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
}
|
||||
|
||||
/*
|
||||
* If you are looking for Object* overloads, use AutoObjectRooter instead;
|
||||
* rooting Object*s as a js::Value requires discerning whether or not it is
|
||||
@ -1537,11 +1530,6 @@ class AutoValueRooter : private AutoGCRooter
|
||||
val = v;
|
||||
}
|
||||
|
||||
void set(jsval v) {
|
||||
JS_ASSERT(tag == JSVAL);
|
||||
val = js::Valueify(v);
|
||||
}
|
||||
|
||||
const Value &value() const {
|
||||
JS_ASSERT(tag == JSVAL);
|
||||
return val;
|
||||
@ -1637,14 +1625,6 @@ class AutoArrayRooter : private AutoGCRooter {
|
||||
JS_ASSERT(tag >= 0);
|
||||
}
|
||||
|
||||
AutoArrayRooter(JSContext *cx, size_t len, jsval *vec
|
||||
JS_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
: AutoGCRooter(cx, len), array(Valueify(vec))
|
||||
{
|
||||
JS_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
JS_ASSERT(tag >= 0);
|
||||
}
|
||||
|
||||
void changeLength(size_t newLength) {
|
||||
tag = ptrdiff_t(newLength);
|
||||
JS_ASSERT(tag >= 0);
|
||||
|
@ -175,10 +175,6 @@ class CompartmentChecker
|
||||
check(v.toString());
|
||||
}
|
||||
|
||||
void check(jsval v) {
|
||||
check(Valueify(v));
|
||||
}
|
||||
|
||||
void check(const ValueArray &arr) {
|
||||
for (size_t i = 0; i < arr.length; i++)
|
||||
check(arr.array[i]);
|
||||
@ -430,7 +426,7 @@ inline void
|
||||
JSContext::setPendingException(js::Value v) {
|
||||
this->throwing = true;
|
||||
this->exception = v;
|
||||
assertSameCompartment(this, v);
|
||||
js::assertSameCompartment(this, v);
|
||||
}
|
||||
|
||||
inline bool
|
||||
|
@ -1150,7 +1150,7 @@ struct WrapperHasher
|
||||
typedef Value Lookup;
|
||||
|
||||
static HashNumber hash(Value key) {
|
||||
uint64 bits = JSVAL_BITS(Jsvalify(key));
|
||||
uint64 bits = key.asRawBits();
|
||||
return (uint32)bits ^ (uint32)(bits >> 32);
|
||||
}
|
||||
|
||||
|
@ -86,7 +86,6 @@
|
||||
|
||||
using namespace js;
|
||||
using namespace js::types;
|
||||
using namespace mozilla;
|
||||
|
||||
#ifndef JS_HAVE_STDINT_H /* Native support is innocent until proven guilty. */
|
||||
|
||||
|
@ -635,7 +635,7 @@ JSObject::setFlatClosureUpvars(js::Value *upvars)
|
||||
{
|
||||
JS_ASSERT(isFunction());
|
||||
JS_ASSERT(getFunctionPrivate()->isFlatClosure());
|
||||
setFixedSlot(JSSLOT_FLAT_CLOSURE_UPVARS, PrivateValue(upvars));
|
||||
setFixedSlot(JSSLOT_FLAT_CLOSURE_UPVARS, js::PrivateValue(upvars));
|
||||
}
|
||||
|
||||
inline bool
|
||||
@ -864,7 +864,7 @@ JSObject::init(JSContext *cx, js::Class *aclasp, js::types::TypeObject *type,
|
||||
slots = fixedSlots();
|
||||
flags |= PACKED_ARRAY;
|
||||
} else {
|
||||
ClearValueRange(fixedSlots(), capacity, denseArray);
|
||||
js::ClearValueRange(fixedSlots(), capacity, denseArray);
|
||||
}
|
||||
|
||||
newType = NULL;
|
||||
|
@ -54,7 +54,7 @@
|
||||
* make dependency induced by this file should not prove painful.
|
||||
*/
|
||||
|
||||
#include "jspubtd.h"
|
||||
#include "jsapi.h"
|
||||
#include "jsstaticcheck.h"
|
||||
#include "jsutil.h"
|
||||
|
||||
@ -122,6 +122,7 @@ class JSStaticAtom;
|
||||
class JSRope;
|
||||
class JSAtom;
|
||||
struct JSDefinition;
|
||||
class JSWrapper;
|
||||
|
||||
namespace js {
|
||||
|
||||
|
521
js/src/jspubtd.h
521
js/src/jspubtd.h
@ -44,7 +44,52 @@
|
||||
*/
|
||||
#include "jstypes.h"
|
||||
#include "jscompat.h"
|
||||
#include "jsval.h"
|
||||
|
||||
/*
|
||||
* Allow headers to reference JS::Value without #including the whole jsapi.h.
|
||||
* Unfortunately, typedefs (hence jsval) cannot be declared.
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
namespace JS { class Value; }
|
||||
#endif
|
||||
|
||||
/*
|
||||
* In release builds, jsid is defined to be an integral type. This
|
||||
* prevents many bugs from being caught at compile time. E.g.:
|
||||
*
|
||||
* jsid id = ...
|
||||
* if (id == JS_TRUE) // error
|
||||
* ...
|
||||
*
|
||||
* size_t n = id; // error
|
||||
*
|
||||
* To catch more errors, jsid is given a struct type in C++ debug builds.
|
||||
* Struct assignment and (in C++) operator== allow correct code to be mostly
|
||||
* oblivious to the change. This feature can be explicitly disabled in debug
|
||||
* builds by defining JS_NO_JSVAL_JSID_STRUCT_TYPES.
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
|
||||
# if defined(DEBUG) && !defined(JS_NO_JSVAL_JSID_STRUCT_TYPES)
|
||||
# define JS_USE_JSID_STRUCT_TYPES
|
||||
# endif
|
||||
|
||||
# ifdef JS_USE_JSID_STRUCT_TYPES
|
||||
struct jsid
|
||||
{
|
||||
size_t asBits;
|
||||
bool operator==(jsid rhs) const { return asBits == rhs.asBits; }
|
||||
bool operator!=(jsid rhs) const { return asBits != rhs.asBits; }
|
||||
};
|
||||
# define JSID_BITS(id) (id.asBits)
|
||||
# else /* defined(JS_USE_JSID_STRUCT_TYPES) */
|
||||
typedef ptrdiff_t jsid;
|
||||
# define JSID_BITS(id) (id)
|
||||
# endif /* defined(JS_USE_JSID_STRUCT_TYPES) */
|
||||
#else /* defined(__cplusplus) */
|
||||
typedef ptrdiff_t jsid;
|
||||
# define JSID_BITS(id) (id)
|
||||
#endif
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
@ -60,7 +105,6 @@ typedef wchar_t jschar;
|
||||
typedef JSUint16 jschar;
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Run-time version enumeration. See jsversion.h for compile-time counterparts
|
||||
* to these values that may be selected by the JS_VERSION macro, and tested by
|
||||
@ -143,437 +187,60 @@ typedef enum JSIterateOp {
|
||||
JSENUMERATE_DESTROY
|
||||
} JSIterateOp;
|
||||
|
||||
/* See JSVAL_TRACE_KIND and JSTraceCallback in jsapi.h. */
|
||||
typedef enum {
|
||||
JSTRACE_OBJECT,
|
||||
JSTRACE_STRING,
|
||||
JSTRACE_SCRIPT,
|
||||
|
||||
/*
|
||||
* Trace kinds internal to the engine. The embedding can only them if it
|
||||
* implements JSTraceCallback.
|
||||
*/
|
||||
#if JS_HAS_XML_SUPPORT
|
||||
JSTRACE_XML,
|
||||
#endif
|
||||
JSTRACE_SHAPE,
|
||||
JSTRACE_TYPE_OBJECT,
|
||||
JSTRACE_LAST = JSTRACE_TYPE_OBJECT
|
||||
} JSGCTraceKind;
|
||||
|
||||
/* Struct typedefs. */
|
||||
typedef struct JSClass JSClass;
|
||||
typedef struct JSConstDoubleSpec JSConstDoubleSpec;
|
||||
typedef struct JSContext JSContext;
|
||||
typedef struct JSErrorReport JSErrorReport;
|
||||
typedef struct JSFunction JSFunction;
|
||||
typedef struct JSFunctionSpec JSFunctionSpec;
|
||||
typedef struct JSTracer JSTracer;
|
||||
typedef struct JSIdArray JSIdArray;
|
||||
typedef struct JSPropertyDescriptor JSPropertyDescriptor;
|
||||
typedef struct JSPropertySpec JSPropertySpec;
|
||||
typedef struct JSObjectMap JSObjectMap;
|
||||
typedef struct JSRuntime JSRuntime;
|
||||
typedef struct JSStackFrame JSStackFrame;
|
||||
typedef struct JSXDRState JSXDRState;
|
||||
typedef struct JSExceptionState JSExceptionState;
|
||||
typedef struct JSLocaleCallbacks JSLocaleCallbacks;
|
||||
typedef struct JSSecurityCallbacks JSSecurityCallbacks;
|
||||
typedef struct JSCompartment JSCompartment;
|
||||
typedef struct JSCrossCompartmentCall JSCrossCompartmentCall;
|
||||
typedef struct JSClass JSClass;
|
||||
typedef struct JSCompartment JSCompartment;
|
||||
typedef struct JSConstDoubleSpec JSConstDoubleSpec;
|
||||
typedef struct JSContext JSContext;
|
||||
typedef struct JSCrossCompartmentCall JSCrossCompartmentCall;
|
||||
typedef struct JSErrorReport JSErrorReport;
|
||||
typedef struct JSExceptionState JSExceptionState;
|
||||
typedef struct JSFunction JSFunction;
|
||||
typedef struct JSFunctionSpec JSFunctionSpec;
|
||||
typedef struct JSIdArray JSIdArray;
|
||||
typedef struct JSLocaleCallbacks JSLocaleCallbacks;
|
||||
typedef struct JSObject JSObject;
|
||||
typedef struct JSObjectMap JSObjectMap;
|
||||
typedef struct JSPrincipals JSPrincipals;
|
||||
typedef struct JSPropertyDescriptor JSPropertyDescriptor;
|
||||
typedef struct JSPropertyName JSPropertyName;
|
||||
typedef struct JSPropertySpec JSPropertySpec;
|
||||
typedef struct JSRuntime JSRuntime;
|
||||
typedef struct JSSecurityCallbacks JSSecurityCallbacks;
|
||||
typedef struct JSStackFrame JSStackFrame;
|
||||
typedef struct JSScript JSScript;
|
||||
typedef struct JSStructuredCloneWriter JSStructuredCloneWriter;
|
||||
typedef struct JSStructuredCloneReader JSStructuredCloneReader;
|
||||
typedef struct JSStructuredCloneCallbacks JSStructuredCloneCallbacks;
|
||||
typedef struct JSPropertyName JSPropertyName;
|
||||
typedef struct JSStructuredCloneCallbacks JSStructuredCloneCallbacks;
|
||||
typedef struct JSStructuredCloneReader JSStructuredCloneReader;
|
||||
typedef struct JSStructuredCloneWriter JSStructuredCloneWriter;
|
||||
typedef struct JSTracer JSTracer;
|
||||
typedef struct JSXDRState JSXDRState;
|
||||
|
||||
#ifdef __cplusplus
|
||||
typedef class JSWrapper JSWrapper;
|
||||
typedef class JSCrossCompartmentWrapper JSCrossCompartmentWrapper;
|
||||
class JSFlatString;
|
||||
class JSString;
|
||||
#else
|
||||
typedef struct JSFlatString JSFlatString;
|
||||
typedef struct JSString JSString;
|
||||
#endif
|
||||
|
||||
/* JSClass (and js::ObjectOps where appropriate) function pointer typedefs. */
|
||||
|
||||
/*
|
||||
* Add, delete, or get a property named by id in obj. Note the jsid id
|
||||
* type -- id may be a string (Unicode property identifier) or an int (element
|
||||
* index). The *vp out parameter, on success, is the new property value after
|
||||
* an add or get. After a successful delete, *vp is JSVAL_FALSE iff
|
||||
* obj[id] can't be deleted (because it's permanent).
|
||||
*/
|
||||
typedef JSBool
|
||||
(* JSPropertyOp)(JSContext *cx, JSObject *obj, jsid id, jsval *vp);
|
||||
|
||||
/*
|
||||
* Set a property named by id in obj, treating the assignment as strict
|
||||
* mode code if strict is true. Note the jsid id type -- id may be a string
|
||||
* (Unicode property identifier) or an int (element index). The *vp out
|
||||
* parameter, on success, is the new property value after the
|
||||
* set.
|
||||
*/
|
||||
typedef JSBool
|
||||
(* JSStrictPropertyOp)(JSContext *cx, JSObject *obj, jsid id, JSBool strict, jsval *vp);
|
||||
|
||||
/*
|
||||
* This function type is used for callbacks that enumerate the properties of
|
||||
* a JSObject. The behavior depends on the value of enum_op:
|
||||
*
|
||||
* JSENUMERATE_INIT
|
||||
* A new, opaque iterator state should be allocated and stored in *statep.
|
||||
* (You can use PRIVATE_TO_JSVAL() to tag the pointer to be stored).
|
||||
*
|
||||
* The number of properties that will be enumerated should be returned as
|
||||
* an integer jsval in *idp, if idp is non-null, and provided the number of
|
||||
* enumerable properties is known. If idp is non-null and the number of
|
||||
* enumerable properties can't be computed in advance, *idp should be set
|
||||
* to JSVAL_ZERO.
|
||||
*
|
||||
* JSENUMERATE_INIT_ALL
|
||||
* Used identically to JSENUMERATE_INIT, but exposes all properties of the
|
||||
* object regardless of enumerability.
|
||||
*
|
||||
* JSENUMERATE_NEXT
|
||||
* A previously allocated opaque iterator state is passed in via statep.
|
||||
* Return the next jsid in the iteration using *idp. The opaque iterator
|
||||
* state pointed at by statep is destroyed and *statep is set to JSVAL_NULL
|
||||
* if there are no properties left to enumerate.
|
||||
*
|
||||
* JSENUMERATE_DESTROY
|
||||
* Destroy the opaque iterator state previously allocated in *statep by a
|
||||
* call to this function when enum_op was JSENUMERATE_INIT or
|
||||
* JSENUMERATE_INIT_ALL.
|
||||
*
|
||||
* The return value is used to indicate success, with a value of JS_FALSE
|
||||
* indicating failure.
|
||||
*/
|
||||
typedef JSBool
|
||||
(* JSNewEnumerateOp)(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
|
||||
jsval *statep, jsid *idp);
|
||||
|
||||
/*
|
||||
* The old-style JSClass.enumerate op should define all lazy properties not
|
||||
* yet reflected in obj.
|
||||
*/
|
||||
typedef JSBool
|
||||
(* JSEnumerateOp)(JSContext *cx, JSObject *obj);
|
||||
|
||||
/*
|
||||
* Resolve a lazy property named by id in obj by defining it directly in obj.
|
||||
* Lazy properties are those reflected from some peer native property space
|
||||
* (e.g., the DOM attributes for a given node reflected as obj) on demand.
|
||||
*
|
||||
* JS looks for a property in an object, and if not found, tries to resolve
|
||||
* the given id. If resolve succeeds, the engine looks again in case resolve
|
||||
* defined obj[id]. If no such property exists directly in obj, the process
|
||||
* is repeated with obj's prototype, etc.
|
||||
*
|
||||
* NB: JSNewResolveOp provides a cheaper way to resolve lazy properties.
|
||||
*/
|
||||
typedef JSBool
|
||||
(* JSResolveOp)(JSContext *cx, JSObject *obj, jsid id);
|
||||
|
||||
/*
|
||||
* Like JSResolveOp, but flags provide contextual information as follows:
|
||||
*
|
||||
* JSRESOLVE_QUALIFIED a qualified property id: obj.id or obj[id], not id
|
||||
* JSRESOLVE_ASSIGNING obj[id] is on the left-hand side of an assignment
|
||||
* JSRESOLVE_DETECTING 'if (o.p)...' or similar detection opcode sequence
|
||||
* JSRESOLVE_DECLARING var, const, or function prolog declaration opcode
|
||||
* JSRESOLVE_CLASSNAME class name used when constructing
|
||||
*
|
||||
* The *objp out parameter, on success, should be null to indicate that id
|
||||
* was not resolved; and non-null, referring to obj or one of its prototypes,
|
||||
* if id was resolved.
|
||||
*
|
||||
* This hook instead of JSResolveOp is called via the JSClass.resolve member
|
||||
* if JSCLASS_NEW_RESOLVE is set in JSClass.flags.
|
||||
*
|
||||
* Setting JSCLASS_NEW_RESOLVE and JSCLASS_NEW_RESOLVE_GETS_START further
|
||||
* extends this hook by passing in the starting object on the prototype chain
|
||||
* via *objp. Thus a resolve hook implementation may define the property id
|
||||
* being resolved in the object in which the id was first sought, rather than
|
||||
* in a prototype object whose class led to the resolve hook being called.
|
||||
*
|
||||
* When using JSCLASS_NEW_RESOLVE_GETS_START, the resolve hook must therefore
|
||||
* null *objp to signify "not resolved". With only JSCLASS_NEW_RESOLVE and no
|
||||
* JSCLASS_NEW_RESOLVE_GETS_START, the hook can assume *objp is null on entry.
|
||||
* This is not good practice, but enough existing hook implementations count
|
||||
* on it that we can't break compatibility by passing the starting object in
|
||||
* *objp without a new JSClass flag.
|
||||
*/
|
||||
typedef JSBool
|
||||
(* JSNewResolveOp)(JSContext *cx, JSObject *obj, jsid id, uintN flags,
|
||||
JSObject **objp);
|
||||
|
||||
/*
|
||||
* Convert obj to the given type, returning true with the resulting value in
|
||||
* *vp on success, and returning false on error or exception.
|
||||
*/
|
||||
typedef JSBool
|
||||
(* JSConvertOp)(JSContext *cx, JSObject *obj, JSType type, jsval *vp);
|
||||
|
||||
/*
|
||||
* Delegate typeof to an object so it can cloak a primitive or another object.
|
||||
*/
|
||||
typedef JSType
|
||||
(* JSTypeOfOp)(JSContext *cx, JSObject *obj);
|
||||
|
||||
/*
|
||||
* Finalize obj, which the garbage collector has determined to be unreachable
|
||||
* from other live objects or from GC roots. Obviously, finalizers must never
|
||||
* store a reference to obj.
|
||||
*/
|
||||
typedef void
|
||||
(* JSFinalizeOp)(JSContext *cx, JSObject *obj);
|
||||
|
||||
/*
|
||||
* Used by JS_AddExternalStringFinalizer and JS_RemoveExternalStringFinalizer
|
||||
* to extend and reduce the set of string types finalized by the GC.
|
||||
*/
|
||||
typedef void
|
||||
(* JSStringFinalizeOp)(JSContext *cx, JSString *str);
|
||||
|
||||
/*
|
||||
* JSClass.checkAccess type: check whether obj[id] may be accessed per mode,
|
||||
* returning false on error/exception, true on success with obj[id]'s last-got
|
||||
* value in *vp, and its attributes in *attrsp. As for JSPropertyOp above, id
|
||||
* is either a string or an int jsval.
|
||||
*/
|
||||
typedef JSBool
|
||||
(* JSCheckAccessOp)(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode,
|
||||
jsval *vp);
|
||||
|
||||
/*
|
||||
* Encode or decode an object, given an XDR state record representing external
|
||||
* data. See jsxdrapi.h.
|
||||
*/
|
||||
typedef JSBool
|
||||
(* JSXDRObjectOp)(JSXDRState *xdr, JSObject **objp);
|
||||
|
||||
/*
|
||||
* Check whether v is an instance of obj. Return false on error or exception,
|
||||
* true on success with JS_TRUE in *bp if v is an instance of obj, JS_FALSE in
|
||||
* *bp otherwise.
|
||||
*/
|
||||
typedef JSBool
|
||||
(* JSHasInstanceOp)(JSContext *cx, JSObject *obj, const jsval *v, JSBool *bp);
|
||||
|
||||
/*
|
||||
* Function type for trace operation of the class called to enumerate all
|
||||
* traceable things reachable from obj's private data structure. For each such
|
||||
* thing, a trace implementation must call
|
||||
*
|
||||
* JS_CallTracer(trc, thing, kind);
|
||||
*
|
||||
* or one of its convenience macros as described in jsapi.h.
|
||||
*
|
||||
* JSTraceOp implementation can assume that no other threads mutates object
|
||||
* state. It must not change state of the object or corresponding native
|
||||
* structures. The only exception for this rule is the case when the embedding
|
||||
* needs a tight integration with GC. In that case the embedding can check if
|
||||
* the traversal is a part of the marking phase through calling
|
||||
* JS_IsGCMarkingTracer and apply a special code like emptying caches or
|
||||
* marking its native structures.
|
||||
*/
|
||||
typedef void
|
||||
(* JSTraceOp)(JSTracer *trc, JSObject *obj);
|
||||
|
||||
/*
|
||||
* DEBUG only callback that JSTraceOp implementation can provide to return
|
||||
* a string describing the reference traced with JS_CallTracer.
|
||||
*/
|
||||
typedef void
|
||||
(* JSTraceNamePrinter)(JSTracer *trc, char *buf, size_t bufsize);
|
||||
|
||||
typedef JSBool
|
||||
(* JSEqualityOp)(JSContext *cx, JSObject *obj, const jsval *v, JSBool *bp);
|
||||
|
||||
/*
|
||||
* Typedef for native functions called by the JS VM.
|
||||
*
|
||||
* See jsapi.h, the JS_CALLEE, JS_THIS, etc. macros.
|
||||
*/
|
||||
|
||||
typedef JSBool
|
||||
(* JSNative)(JSContext *cx, uintN argc, jsval *vp);
|
||||
|
||||
/* Callbacks and their arguments. */
|
||||
|
||||
typedef enum JSContextOp {
|
||||
JSCONTEXT_NEW,
|
||||
JSCONTEXT_DESTROY
|
||||
} JSContextOp;
|
||||
|
||||
/*
|
||||
* The possible values for contextOp when the runtime calls the callback are:
|
||||
* JSCONTEXT_NEW JS_NewContext successfully created a new JSContext
|
||||
* instance. The callback can initialize the instance as
|
||||
* required. If the callback returns false, the instance
|
||||
* will be destroyed and JS_NewContext returns null. In
|
||||
* this case the callback is not called again.
|
||||
* JSCONTEXT_DESTROY One of JS_DestroyContext* methods is called. The
|
||||
* callback may perform its own cleanup and must always
|
||||
* return true.
|
||||
* Any other value For future compatibility the callback must do nothing
|
||||
* and return true in this case.
|
||||
*/
|
||||
typedef JSBool
|
||||
(* JSContextCallback)(JSContext *cx, uintN contextOp);
|
||||
|
||||
#ifndef JS_THREADSAFE
|
||||
typedef void
|
||||
(* JSHeartbeatCallback)(JSRuntime *rt);
|
||||
#endif
|
||||
|
||||
typedef enum JSGCStatus {
|
||||
JSGC_BEGIN,
|
||||
JSGC_END,
|
||||
JSGC_MARK_END,
|
||||
JSGC_FINALIZE_END
|
||||
} JSGCStatus;
|
||||
|
||||
typedef JSBool
|
||||
(* JSGCCallback)(JSContext *cx, JSGCStatus status);
|
||||
|
||||
/*
|
||||
* Generic trace operation that calls JS_CallTracer on each traceable thing
|
||||
* stored in data.
|
||||
*/
|
||||
typedef void
|
||||
(* JSTraceDataOp)(JSTracer *trc, void *data);
|
||||
|
||||
typedef JSBool
|
||||
(* JSOperationCallback)(JSContext *cx);
|
||||
|
||||
typedef void
|
||||
(* JSErrorReporter)(JSContext *cx, const char *message, JSErrorReport *report);
|
||||
|
||||
/*
|
||||
* Possible exception types. These types are part of a JSErrorFormatString
|
||||
* structure. They define which error to throw in case of a runtime error.
|
||||
* JSEXN_NONE marks an unthrowable error.
|
||||
*/
|
||||
typedef enum JSExnType {
|
||||
JSEXN_NONE = -1,
|
||||
JSEXN_ERR,
|
||||
JSEXN_INTERNALERR,
|
||||
JSEXN_EVALERR,
|
||||
JSEXN_RANGEERR,
|
||||
JSEXN_REFERENCEERR,
|
||||
JSEXN_SYNTAXERR,
|
||||
JSEXN_TYPEERR,
|
||||
JSEXN_URIERR,
|
||||
JSEXN_LIMIT
|
||||
} JSExnType;
|
||||
|
||||
typedef struct JSErrorFormatString {
|
||||
/* The error format string (UTF-8 if js_CStringsAreUTF8). */
|
||||
const char *format;
|
||||
|
||||
/* The number of arguments to expand in the formatted error message. */
|
||||
uint16 argCount;
|
||||
|
||||
/* One of the JSExnType constants above. */
|
||||
int16 exnType;
|
||||
} JSErrorFormatString;
|
||||
|
||||
typedef const JSErrorFormatString *
|
||||
(* JSErrorCallback)(void *userRef, const char *locale,
|
||||
const uintN errorNumber);
|
||||
|
||||
#ifdef va_start
|
||||
#define JS_ARGUMENT_FORMATTER_DEFINED 1
|
||||
|
||||
typedef JSBool
|
||||
(* JSArgumentFormatter)(JSContext *cx, const char *format, JSBool fromJS,
|
||||
jsval **vpp, va_list *app);
|
||||
#endif
|
||||
|
||||
typedef JSBool
|
||||
(* JSLocaleToUpperCase)(JSContext *cx, JSString *src, jsval *rval);
|
||||
|
||||
typedef JSBool
|
||||
(* JSLocaleToLowerCase)(JSContext *cx, JSString *src, jsval *rval);
|
||||
|
||||
typedef JSBool
|
||||
(* JSLocaleCompare)(JSContext *cx, JSString *src1, JSString *src2,
|
||||
jsval *rval);
|
||||
|
||||
typedef JSBool
|
||||
(* JSLocaleToUnicode)(JSContext *cx, const char *src, jsval *rval);
|
||||
|
||||
/*
|
||||
* Security protocol types.
|
||||
*/
|
||||
typedef struct JSPrincipals JSPrincipals;
|
||||
|
||||
/*
|
||||
* XDR-encode or -decode a principals instance, based on whether xdr->mode is
|
||||
* JSXDR_ENCODE, in which case *principalsp should be encoded; or JSXDR_DECODE,
|
||||
* in which case implementations must return a held (via JSPRINCIPALS_HOLD),
|
||||
* non-null *principalsp out parameter. Return true on success, false on any
|
||||
* error, which the implementation must have reported.
|
||||
*/
|
||||
typedef JSBool
|
||||
(* JSPrincipalsTranscoder)(JSXDRState *xdr, JSPrincipals **principalsp);
|
||||
|
||||
/*
|
||||
* Return a weak reference to the principals associated with obj, possibly via
|
||||
* the immutable parent chain leading from obj to a top-level container (e.g.,
|
||||
* a window object in the DOM level 0). If there are no principals associated
|
||||
* with obj, return null. Therefore null does not mean an error was reported;
|
||||
* in no event should an error be reported or an exception be thrown by this
|
||||
* callback's implementation.
|
||||
*/
|
||||
typedef JSPrincipals *
|
||||
(* JSObjectPrincipalsFinder)(JSContext *cx, JSObject *obj);
|
||||
|
||||
/*
|
||||
* Used to check if a CSP instance wants to disable eval() and friends.
|
||||
* See js_CheckCSPPermitsJSAction() in jsobj.
|
||||
*/
|
||||
typedef JSBool
|
||||
(* JSCSPEvalChecker)(JSContext *cx);
|
||||
|
||||
/*
|
||||
* Callback used to ask the embedding for the cross compartment wrapper handler
|
||||
* that implements the desired prolicy for this kind of object in the
|
||||
* destination compartment.
|
||||
*/
|
||||
typedef JSObject *
|
||||
(* JSWrapObjectCallback)(JSContext *cx, JSObject *obj, JSObject *proto, JSObject *parent,
|
||||
uintN flags);
|
||||
|
||||
/*
|
||||
* Callback used by the wrap hook to ask the embedding to prepare an object
|
||||
* for wrapping in a context. This might include unwrapping other wrappers
|
||||
* or even finding a more suitable object for the new compartment.
|
||||
*/
|
||||
typedef JSObject *
|
||||
(* JSPreWrapCallback)(JSContext *cx, JSObject *scope, JSObject *obj, uintN flags);
|
||||
|
||||
typedef enum {
|
||||
JSCOMPARTMENT_DESTROY
|
||||
} JSCompartmentOp;
|
||||
|
||||
typedef JSBool
|
||||
(* JSCompartmentCallback)(JSContext *cx, JSCompartment *compartment, uintN compartmentOp);
|
||||
|
||||
/*
|
||||
* Read structured data from the reader r. This hook is used to read a value
|
||||
* previously serialized by a call to the WriteStructuredCloneOp hook.
|
||||
*
|
||||
* tag and data are the pair of uint32 values from the header. The callback may
|
||||
* use the JS_Read* APIs to read any other relevant parts of the object from
|
||||
* the reader r. closure is any value passed to the JS_ReadStructuredClone
|
||||
* function. Return the new object on success, NULL on error/exception.
|
||||
*/
|
||||
typedef JSObject *(*ReadStructuredCloneOp)(JSContext *cx, JSStructuredCloneReader *r,
|
||||
uint32 tag, uint32 data, void *closure);
|
||||
|
||||
/*
|
||||
* Structured data serialization hook. The engine can write primitive values,
|
||||
* Objects, Arrays, Dates, RegExps, TypedArrays, and ArrayBuffers. Any other
|
||||
* type of object requires application support. This callback must first use
|
||||
* the JS_WriteUint32Pair API to write an object header, passing a value
|
||||
* greater than JS_SCTAG_USER to the tag parameter. Then it can use the
|
||||
* JS_Write* APIs to write any other relevant parts of the value v to the
|
||||
* writer w. closure is any value passed to the JS_WriteStructuredCLone function.
|
||||
*
|
||||
* Return true on success, false on error/exception.
|
||||
*/
|
||||
typedef JSBool (*WriteStructuredCloneOp)(JSContext *cx, JSStructuredCloneWriter *w,
|
||||
JSObject *obj, void *closure);
|
||||
|
||||
/*
|
||||
* This is called when JS_WriteStructuredClone finds that the object to be
|
||||
* written is recursive. To follow HTML5, the application must throw a
|
||||
* DATA_CLONE_ERR DOMException. errorid is always JS_SCERR_RECURSION.
|
||||
*/
|
||||
typedef void (*StructuredCloneErrorOp)(JSContext *cx, uint32 errorid);
|
||||
|
||||
JS_END_EXTERN_C
|
||||
|
||||
#endif /* jspubtd_h___ */
|
||||
|
@ -9941,7 +9941,7 @@ TraceRecorder::box_value_for_native_call(const Value &v, LIns *v_ins)
|
||||
void
|
||||
TraceRecorder::box_undefined_into(Address addr)
|
||||
{
|
||||
w.stq(w.nameImmq(JSVAL_BITS(JSVAL_VOID)), addr);
|
||||
w.stq(w.nameImmq(JSVAL_VOID.asRawBits()), addr);
|
||||
}
|
||||
|
||||
inline LIns *
|
||||
@ -10043,14 +10043,14 @@ LIns*
|
||||
TraceRecorder::is_boxed_true(Address addr)
|
||||
{
|
||||
LIns *v_ins = w.ldq(addr);
|
||||
return w.eqq(v_ins, w.immq(JSVAL_BITS(JSVAL_TRUE)));
|
||||
return w.eqq(v_ins, w.immq(JSVAL_TRUE.asRawBits()));
|
||||
}
|
||||
|
||||
LIns*
|
||||
TraceRecorder::is_boxed_magic(Address addr, JSWhyMagic why)
|
||||
{
|
||||
LIns *v_ins = w.ldq(addr);
|
||||
return w.eqq(v_ins, w.nameImmq(BUILD_JSVAL(JSVAL_TAG_MAGIC, why)));
|
||||
return w.eqq(v_ins, w.nameImmq(MagicValue(why).asRawBits()));
|
||||
}
|
||||
|
||||
LIns*
|
||||
@ -10068,9 +10068,9 @@ TraceRecorder::box_value_for_native_call(const Value &v, LIns *v_ins)
|
||||
}
|
||||
|
||||
if (v.isNull())
|
||||
return w.nameImmq(JSVAL_BITS(JSVAL_NULL));
|
||||
return w.nameImmq(JSVAL_NULL.asRawBits());
|
||||
if (v.isUndefined())
|
||||
return w.nameImmq(JSVAL_BITS(JSVAL_VOID));
|
||||
return w.nameImmq(JSVAL_VOID.asRawBits());
|
||||
|
||||
JSValueTag tag = v.isObject() ? JSVAL_TAG_OBJECT : v.extractNonDoubleObjectTraceTag();
|
||||
uint64 shiftedTag = ((uint64)tag) << JSVAL_TAG_SHIFT;
|
||||
@ -14849,7 +14849,7 @@ TraceRecorder::storeMagic(JSWhyMagic why, Address addr)
|
||||
JS_REQUIRES_STACK void
|
||||
TraceRecorder::storeMagic(JSWhyMagic why, Address addr)
|
||||
{
|
||||
LIns *magic = w.nameImmq(BUILD_JSVAL(JSVAL_TAG_MAGIC, why));
|
||||
LIns *magic = w.nameImmq(MagicValue(why).asRawBits());
|
||||
w.stq(magic, addr);
|
||||
}
|
||||
#endif
|
||||
|
@ -49,6 +49,25 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
/* The public JS engine namespace. */
|
||||
namespace JS {}
|
||||
|
||||
/* The mozilla-shared reusable template/utility namespace. */
|
||||
namespace mozilla {}
|
||||
|
||||
/* The private JS engine namespace. */
|
||||
namespace js {
|
||||
|
||||
/* The private namespace is a superset of the public/shared namespaces. */
|
||||
using namespace JS;
|
||||
using namespace mozilla;
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
#endif /* defined __cplusplus */
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
#define JS_CRASH_UNLESS(__cond) \
|
||||
@ -484,8 +503,6 @@ JS_END_EXTERN_C
|
||||
* be used, though this is undesirable.
|
||||
*/
|
||||
namespace js {
|
||||
/* Import common mfbt declarations into "js". */
|
||||
using namespace mozilla;
|
||||
|
||||
class OffTheBooks {
|
||||
public:
|
||||
|
340
js/src/jsval.h
340
js/src/jsval.h
@ -40,15 +40,50 @@
|
||||
#ifndef jsvalimpl_h__
|
||||
#define jsvalimpl_h__
|
||||
/*
|
||||
* JS value implementation details for operations on jsval and jsid.
|
||||
* Embeddings should not rely on any of the definitions in this file. For a
|
||||
* description of the value representation and the engine-internal C++ value
|
||||
* interface, js::Value, see jsvalue.h.
|
||||
* Implementation details for js::Value in jsapi.h.
|
||||
*/
|
||||
#include "jsutil.h"
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
/* To avoid a circular dependency, pull in the necessary pieces of jsnum.h. */
|
||||
|
||||
#define JSDOUBLE_SIGNBIT (((uint64) 1) << 63)
|
||||
#define JSDOUBLE_EXPMASK (((uint64) 0x7ff) << 52)
|
||||
#define JSDOUBLE_MANTMASK ((((uint64) 1) << 52) - 1)
|
||||
#define JSDOUBLE_HI32_SIGNBIT 0x80000000
|
||||
|
||||
static JS_ALWAYS_INLINE JSBool
|
||||
JSDOUBLE_IS_NEGZERO(double d)
|
||||
{
|
||||
union {
|
||||
struct {
|
||||
#if defined(IS_LITTLE_ENDIAN) && !defined(FPU_IS_ARM_FPA)
|
||||
uint32 lo, hi;
|
||||
#else
|
||||
uint32 hi, lo;
|
||||
#endif
|
||||
} s;
|
||||
double d;
|
||||
} x;
|
||||
if (d != 0)
|
||||
return JS_FALSE;
|
||||
x.d = d;
|
||||
return (x.s.hi & JSDOUBLE_HI32_SIGNBIT) != 0;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSBool
|
||||
JSDOUBLE_IS_INT32(double d, int32* pi)
|
||||
{
|
||||
if (JSDOUBLE_IS_NEGZERO(d))
|
||||
return JS_FALSE;
|
||||
return d == (*pi = (int32)d);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
/*
|
||||
* Try to get jsvals 64-bit aligned. We could almost assert that all values are
|
||||
* aligned, but MSVC and GCC occasionally break alignment.
|
||||
@ -271,15 +306,6 @@ typedef enum JSWhyMagic
|
||||
JS_GENERIC_MAGIC /* for local use */
|
||||
} JSWhyMagic;
|
||||
|
||||
#ifdef __cplusplus
|
||||
class JSString;
|
||||
class JSFlatString;
|
||||
#else
|
||||
typedef struct JSString JSString;
|
||||
typedef struct JSFlatString JSFlatString;
|
||||
#endif
|
||||
typedef struct JSObject JSObject;
|
||||
|
||||
#if defined(IS_LITTLE_ENDIAN)
|
||||
# if JS_BITS_PER_WORD == 32
|
||||
typedef union jsval_layout
|
||||
@ -294,7 +320,7 @@ typedef union jsval_layout
|
||||
JSObject *obj;
|
||||
void *ptr;
|
||||
JSWhyMagic why;
|
||||
jsuword word;
|
||||
size_t word;
|
||||
} payload;
|
||||
JSValueTag tag;
|
||||
} s;
|
||||
@ -321,7 +347,7 @@ typedef union jsval_layout
|
||||
} s;
|
||||
double asDouble;
|
||||
void *asPtr;
|
||||
jsuword asWord;
|
||||
size_t asWord;
|
||||
} jsval_layout;
|
||||
# endif /* JS_BITS_PER_WORD */
|
||||
#else /* defined(IS_LITTLE_ENDIAN) */
|
||||
@ -339,7 +365,7 @@ typedef union jsval_layout
|
||||
JSObject *obj;
|
||||
void *ptr;
|
||||
JSWhyMagic why;
|
||||
jsuword word;
|
||||
size_t word;
|
||||
} payload;
|
||||
} s;
|
||||
double asDouble;
|
||||
@ -363,7 +389,7 @@ typedef union jsval_layout
|
||||
} s;
|
||||
double asDouble;
|
||||
void *asPtr;
|
||||
jsuword asWord;
|
||||
size_t asWord;
|
||||
} jsval_layout;
|
||||
# endif /* JS_BITS_PER_WORD */
|
||||
#endif /* defined(IS_LITTLE_ENDIAN) */
|
||||
@ -378,8 +404,13 @@ JS_STATIC_ASSERT(sizeof(jsval_layout) == 8);
|
||||
* Thus, all comparisons should explicitly cast operands to uint32.
|
||||
*/
|
||||
|
||||
#define BUILD_JSVAL(tag, payload) \
|
||||
((((uint64)(uint32)(tag)) << 32) | (uint32)(payload))
|
||||
static JS_ALWAYS_INLINE jsval_layout
|
||||
BUILD_JSVAL(JSValueTag tag, uint32 payload)
|
||||
{
|
||||
jsval_layout l;
|
||||
l.asBits = (((uint64)(uint32)tag) << 32) | payload;
|
||||
return l;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSBool
|
||||
JSVAL_IS_DOUBLE_IMPL(jsval_layout l)
|
||||
@ -571,10 +602,112 @@ JSVAL_TRACE_KIND_IMPL(jsval_layout l)
|
||||
return (uint32)(JSBool)JSVAL_IS_STRING_IMPL(l);
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSBool
|
||||
JSVAL_IS_SPECIFIC_INT32_IMPL(jsval_layout l, int32 i32)
|
||||
{
|
||||
return l.s.tag == JSVAL_TAG_INT32 && l.s.payload.i32 == i32;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSBool
|
||||
JSVAL_IS_SPECIFIC_BOOLEAN(jsval_layout l, JSBool b)
|
||||
{
|
||||
return (l.s.tag == JSVAL_TAG_BOOLEAN) && (l.s.payload.boo == b);
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE jsval_layout
|
||||
MAGIC_TO_JSVAL_IMPL(JSWhyMagic why)
|
||||
{
|
||||
jsval_layout l;
|
||||
l.s.tag = JSVAL_TAG_MAGIC;
|
||||
l.s.payload.why = why;
|
||||
return l;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE jsval_layout
|
||||
MAGIC_OBJ_TO_JSVAL_IMPL(JSObject *obj)
|
||||
{
|
||||
jsval_layout l;
|
||||
l.s.tag = JSVAL_TAG_MAGIC;
|
||||
l.s.payload.obj = obj;
|
||||
return l;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSBool
|
||||
JSVAL_SAME_TYPE_IMPL(jsval_layout lhs, jsval_layout rhs)
|
||||
{
|
||||
JSValueTag ltag = lhs.s.tag, rtag = rhs.s.tag;
|
||||
return ltag == rtag || (ltag < JSVAL_TAG_CLEAR && rtag < JSVAL_TAG_CLEAR);
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE jsval_layout
|
||||
PRIVATE_UINT32_TO_JSVAL_IMPL(uint32 ui)
|
||||
{
|
||||
jsval_layout l;
|
||||
l.s.tag = (JSValueTag)0;
|
||||
l.s.payload.u32 = ui;
|
||||
JS_ASSERT(JSVAL_IS_DOUBLE_IMPL(l));
|
||||
return l;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE uint32
|
||||
JSVAL_TO_PRIVATE_UINT32_IMPL(jsval_layout l)
|
||||
{
|
||||
return l.s.payload.u32;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSValueType
|
||||
JSVAL_EXTRACT_NON_DOUBLE_TYPE_IMPL(jsval_layout l)
|
||||
{
|
||||
uint32 type = l.s.tag & 0xF;
|
||||
JS_ASSERT(type > JSVAL_TYPE_DOUBLE);
|
||||
return (JSValueType)type;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSValueTag
|
||||
JSVAL_EXTRACT_NON_DOUBLE_TAG_IMPL(jsval_layout l)
|
||||
{
|
||||
JSValueTag tag = l.s.tag;
|
||||
JS_ASSERT(tag >= JSVAL_TAG_INT32);
|
||||
return tag;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
JS_STATIC_ASSERT((JSVAL_TYPE_NONFUNOBJ & 0xF) == JSVAL_TYPE_OBJECT);
|
||||
JS_STATIC_ASSERT((JSVAL_TYPE_FUNOBJ & 0xF) == JSVAL_TYPE_OBJECT);
|
||||
#endif
|
||||
|
||||
static JS_ALWAYS_INLINE jsval_layout
|
||||
BOX_NON_DOUBLE_JSVAL(JSValueType type, uint64 *slot)
|
||||
{
|
||||
jsval_layout l;
|
||||
JS_ASSERT(type > JSVAL_TYPE_DOUBLE && type <= JSVAL_UPPER_INCL_TYPE_OF_BOXABLE_SET);
|
||||
JS_ASSERT_IF(type == JSVAL_TYPE_STRING ||
|
||||
type == JSVAL_TYPE_OBJECT ||
|
||||
type == JSVAL_TYPE_NONFUNOBJ ||
|
||||
type == JSVAL_TYPE_FUNOBJ,
|
||||
*(uint32 *)slot != 0);
|
||||
l.s.tag = JSVAL_TYPE_TO_TAG(type & 0xF);
|
||||
/* A 32-bit value in a 64-bit slot always occupies the low-addressed end. */
|
||||
l.s.payload.u32 = *(uint32 *)slot;
|
||||
return l;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE void
|
||||
UNBOX_NON_DOUBLE_JSVAL(jsval_layout l, uint64 *out)
|
||||
{
|
||||
JS_ASSERT(!JSVAL_IS_DOUBLE_IMPL(l));
|
||||
*(uint32 *)out = l.s.payload.u32;
|
||||
}
|
||||
|
||||
#elif JS_BITS_PER_WORD == 64
|
||||
|
||||
#define BUILD_JSVAL(tag, payload) \
|
||||
((((uint64)(uint32)(tag)) << JSVAL_TAG_SHIFT) | (payload))
|
||||
static JS_ALWAYS_INLINE jsval_layout
|
||||
BUILD_JSVAL(JSValueTag tag, uint64 payload)
|
||||
{
|
||||
jsval_layout l;
|
||||
l.asBits = (((uint64)(uint32)tag) << JSVAL_TAG_SHIFT) | payload;
|
||||
return l;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSBool
|
||||
JSVAL_IS_DOUBLE_IMPL(jsval_layout l)
|
||||
@ -771,8 +904,109 @@ JSVAL_TO_PRIVATE_PTR_IMPL(jsval_layout l)
|
||||
return (void *)(l.asBits << 1);
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSBool
|
||||
JSVAL_IS_SPECIFIC_INT32_IMPL(jsval_layout l, int32 i32)
|
||||
{
|
||||
return l.asBits == (((uint64)(uint32)i32) | JSVAL_SHIFTED_TAG_INT32);
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSBool
|
||||
JSVAL_IS_SPECIFIC_BOOLEAN(jsval_layout l, JSBool b)
|
||||
{
|
||||
return l.asBits == (((uint64)(uint32)b) | JSVAL_SHIFTED_TAG_BOOLEAN);
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE jsval_layout
|
||||
MAGIC_TO_JSVAL_IMPL(JSWhyMagic why)
|
||||
{
|
||||
jsval_layout l;
|
||||
l.asBits = ((uint64)(uint32)why) | JSVAL_SHIFTED_TAG_MAGIC;
|
||||
return l;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE jsval_layout
|
||||
MAGIC_OBJ_TO_JSVAL_IMPL(JSObject *obj)
|
||||
{
|
||||
jsval_layout l;
|
||||
l.asBits = ((uint64)obj) | JSVAL_SHIFTED_TAG_MAGIC;
|
||||
return l;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSBool
|
||||
JSVAL_SAME_TYPE_IMPL(jsval_layout lhs, jsval_layout rhs)
|
||||
{
|
||||
uint64 lbits = lhs.asBits, rbits = rhs.asBits;
|
||||
return (lbits <= JSVAL_SHIFTED_TAG_MAX_DOUBLE && rbits <= JSVAL_SHIFTED_TAG_MAX_DOUBLE) ||
|
||||
(((lbits ^ rbits) & 0xFFFF800000000000LL) == 0);
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE jsval_layout
|
||||
PRIVATE_UINT32_TO_JSVAL_IMPL(uint32 ui)
|
||||
{
|
||||
jsval_layout l;
|
||||
l.asBits = (uint64)ui;
|
||||
JS_ASSERT(JSVAL_IS_DOUBLE_IMPL(l));
|
||||
return l;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE uint32
|
||||
JSVAL_TO_PRIVATE_UINT32_IMPL(jsval_layout l)
|
||||
{
|
||||
JS_ASSERT((l.asBits >> 32) == 0);
|
||||
return (uint32)l.asBits;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSValueType
|
||||
JSVAL_EXTRACT_NON_DOUBLE_TYPE_IMPL(jsval_layout l)
|
||||
{
|
||||
uint64 type = (l.asBits >> JSVAL_TAG_SHIFT) & 0xF;
|
||||
JS_ASSERT(type > JSVAL_TYPE_DOUBLE);
|
||||
return (JSValueType)type;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSValueTag
|
||||
JSVAL_EXTRACT_NON_DOUBLE_TAG_IMPL(jsval_layout l)
|
||||
{
|
||||
uint64 tag = l.asBits >> JSVAL_TAG_SHIFT;
|
||||
JS_ASSERT(tag > JSVAL_TAG_MAX_DOUBLE);
|
||||
return (JSValueTag)tag;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
JS_STATIC_ASSERT((JSVAL_TYPE_NONFUNOBJ & 0xF) == JSVAL_TYPE_OBJECT);
|
||||
JS_STATIC_ASSERT((JSVAL_TYPE_FUNOBJ & 0xF) == JSVAL_TYPE_OBJECT);
|
||||
#endif
|
||||
|
||||
static JS_ALWAYS_INLINE jsval_layout
|
||||
BOX_NON_DOUBLE_JSVAL(JSValueType type, uint64 *slot)
|
||||
{
|
||||
uint32 isI32 = (uint32)(type < JSVAL_LOWER_INCL_TYPE_OF_PTR_PAYLOAD_SET);
|
||||
uint32 shift = isI32 * 32;
|
||||
uint64 mask = ((uint64)-1) >> shift;
|
||||
uint64 payload = *slot & mask;
|
||||
jsval_layout l;
|
||||
|
||||
/* N.B. for 32-bit payloads, the high 32 bits of the slot are trash. */
|
||||
JS_ASSERT(type > JSVAL_TYPE_DOUBLE && type <= JSVAL_UPPER_INCL_TYPE_OF_BOXABLE_SET);
|
||||
JS_ASSERT_IF(type == JSVAL_TYPE_STRING ||
|
||||
type == JSVAL_TYPE_OBJECT ||
|
||||
type == JSVAL_TYPE_NONFUNOBJ ||
|
||||
type == JSVAL_TYPE_FUNOBJ,
|
||||
payload != 0);
|
||||
|
||||
l.asBits = payload | JSVAL_TYPE_TO_SHIFTED_TAG(type & 0xF);
|
||||
return l;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE void
|
||||
UNBOX_NON_DOUBLE_JSVAL(jsval_layout l, uint64 *out)
|
||||
{
|
||||
JS_ASSERT(!JSVAL_IS_DOUBLE_IMPL(l));
|
||||
*out = (l.asBits & JSVAL_PAYLOAD_MASK);
|
||||
}
|
||||
|
||||
#endif /* JS_BITS_PER_WORD */
|
||||
|
||||
static JS_ALWAYS_INLINE double
|
||||
JS_CANONICALIZE_NAN(double d)
|
||||
{
|
||||
@ -784,65 +1018,11 @@ JS_CANONICALIZE_NAN(double d)
|
||||
return d;
|
||||
}
|
||||
|
||||
/* See JS_USE_JSVAL_JSID_STRUCT_TYPES comment in jsapi.h. */
|
||||
#if defined(DEBUG) && !defined(JS_NO_JSVAL_JSID_STRUCT_TYPES)
|
||||
# define JS_USE_JSVAL_JSID_STRUCT_TYPES
|
||||
#endif
|
||||
|
||||
#ifdef JS_USE_JSVAL_JSID_STRUCT_TYPES
|
||||
|
||||
typedef JSVAL_ALIGNMENT jsval_layout jsval;
|
||||
typedef struct jsid { size_t asBits; } jsid;
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C++"
|
||||
{
|
||||
static JS_ALWAYS_INLINE bool
|
||||
operator==(jsid lhs, jsid rhs)
|
||||
{
|
||||
return lhs.asBits == rhs.asBits;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE bool
|
||||
operator!=(jsid lhs, jsid rhs)
|
||||
{
|
||||
return lhs.asBits != rhs.asBits;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE bool
|
||||
operator==(jsval lhs, jsval rhs)
|
||||
{
|
||||
return lhs.asBits == rhs.asBits;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE bool
|
||||
operator!=(jsval lhs, jsval rhs)
|
||||
{
|
||||
return lhs.asBits != rhs.asBits;
|
||||
}
|
||||
}
|
||||
# endif /* defined(__cplusplus) */
|
||||
|
||||
/* Internal helper macros */
|
||||
#define JSVAL_BITS(v) ((v).asBits)
|
||||
#define JSVAL_FROM_LAYOUT(l) (l)
|
||||
#define IMPL_TO_JSVAL(v) (v)
|
||||
#define JSID_BITS(id) ((id).asBits)
|
||||
|
||||
#else /* defined(JS_USE_JSVAL_JSID_STRUCT_TYPES) */
|
||||
|
||||
/* Use different primitive types so overloading works. */
|
||||
typedef JSVAL_ALIGNMENT JSUint64 jsval;
|
||||
typedef ptrdiff_t jsid;
|
||||
|
||||
/* Internal helper macros */
|
||||
#define JSVAL_BITS(v) (v)
|
||||
#define JSVAL_FROM_LAYOUT(l) ((l).asBits)
|
||||
#define IMPL_TO_JSVAL(v) ((v).asBits)
|
||||
#define JSID_BITS(id) (id)
|
||||
|
||||
#endif /* defined(JS_USE_JSVAL_JSID_STRUCT_TYPES) */
|
||||
|
||||
JS_END_EXTERN_C
|
||||
|
||||
#ifdef __cplusplus
|
||||
static jsval_layout JSVAL_TO_IMPL(JS::Value);
|
||||
static JS::Value IMPL_TO_JSVAL(jsval_layout);
|
||||
#endif
|
||||
|
||||
#endif /* jsvalimpl_h__ */
|
||||
|
881
js/src/jsvalue.h
881
js/src/jsvalue.h
@ -43,854 +43,9 @@
|
||||
* Private value interface.
|
||||
*/
|
||||
#include "jsprvtd.h"
|
||||
#include "jsstdint.h"
|
||||
|
||||
/*
|
||||
* js::Value is a C++-ified version of jsval that provides more information and
|
||||
* helper functions than the basic jsval interface exposed by jsapi.h. A few
|
||||
* general notes on js::Value:
|
||||
*
|
||||
* - Since js::Value and jsval have the same representation, values of these
|
||||
* types, function pointer types differing only in these types, and structs
|
||||
* differing only in these types can be converted back and forth at no cost
|
||||
* using the Jsvalify() and Valueify(). See Jsvalify comment below.
|
||||
*
|
||||
* - js::Value has setX() and isX() members for X in
|
||||
*
|
||||
* { Int32, Double, String, Boolean, Undefined, Null, Object, Magic }
|
||||
*
|
||||
* js::Value also contains toX() for each of the non-singleton types.
|
||||
*
|
||||
* - Magic is a singleton type whose payload contains a JSWhyMagic "reason" for
|
||||
* the magic value. By providing JSWhyMagic values when creating and checking
|
||||
* for magic values, it is possible to assert, at runtime, that only magic
|
||||
* values with the expected reason flow through a particular value. For
|
||||
* example, if cx->exception has a magic value, the reason must be
|
||||
* JS_GENERATOR_CLOSING.
|
||||
*
|
||||
* - A key difference between jsval and js::Value is that js::Value gives null
|
||||
* a separate type. Thus
|
||||
*
|
||||
* JSVAL_IS_OBJECT(v) === v.isObjectOrNull()
|
||||
* !JSVAL_IS_PRIMITIVE(v) === v.isObject()
|
||||
*
|
||||
* To help prevent mistakenly boxing a nullable JSObject* as an object,
|
||||
* Value::setObject takes a JSObject&. (Conversely, Value::asObject returns a
|
||||
* JSObject&. A convenience member Value::setObjectOrNull is provided.
|
||||
*
|
||||
* - JSVAL_VOID is the same as the singleton value of the Undefined type.
|
||||
*
|
||||
* - Note that js::Value is always 64-bit. Thus, on 32-bit user code should
|
||||
* avoid copying jsval/js::Value as much as possible, preferring to pass by
|
||||
* const Value &.
|
||||
*/
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
/* To avoid a circular dependency, pull in the necessary pieces of jsnum.h. */
|
||||
|
||||
#define JSDOUBLE_SIGNBIT (((uint64) 1) << 63)
|
||||
#define JSDOUBLE_EXPMASK (((uint64) 0x7ff) << 52)
|
||||
#define JSDOUBLE_MANTMASK ((((uint64) 1) << 52) - 1)
|
||||
#define JSDOUBLE_HI32_SIGNBIT 0x80000000
|
||||
|
||||
static JS_ALWAYS_INLINE JSBool
|
||||
JSDOUBLE_IS_NEGZERO(jsdouble d)
|
||||
{
|
||||
if (d != 0)
|
||||
return false;
|
||||
union {
|
||||
struct {
|
||||
#if defined(IS_LITTLE_ENDIAN) && !defined(FPU_IS_ARM_FPA)
|
||||
uint32 lo, hi;
|
||||
#else
|
||||
uint32 hi, lo;
|
||||
#endif
|
||||
} s;
|
||||
jsdouble d;
|
||||
} x;
|
||||
x.d = d;
|
||||
return (x.s.hi & JSDOUBLE_HI32_SIGNBIT) != 0;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
JSDOUBLE_IS_INT32(jsdouble d, int32_t* pi)
|
||||
{
|
||||
if (JSDOUBLE_IS_NEGZERO(d))
|
||||
return false;
|
||||
return d == (*pi = int32_t(d));
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
/* Additional value operations used in js::Value but not in jsapi.h. */
|
||||
|
||||
#if JS_BITS_PER_WORD == 32
|
||||
|
||||
static JS_ALWAYS_INLINE JSBool
|
||||
JSVAL_IS_SPECIFIC_INT32_IMPL(jsval_layout l, int32 i32)
|
||||
{
|
||||
return l.s.tag == JSVAL_TAG_INT32 && l.s.payload.i32 == i32;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSBool
|
||||
JSVAL_IS_SPECIFIC_BOOLEAN(jsval_layout l, JSBool b)
|
||||
{
|
||||
return (l.s.tag == JSVAL_TAG_BOOLEAN) && (l.s.payload.boo == b);
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE jsval_layout
|
||||
MAGIC_TO_JSVAL_IMPL(JSWhyMagic why)
|
||||
{
|
||||
jsval_layout l;
|
||||
l.s.tag = JSVAL_TAG_MAGIC;
|
||||
l.s.payload.why = why;
|
||||
return l;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE jsval_layout
|
||||
MAGIC_TO_JSVAL_IMPL(JSObject *obj)
|
||||
{
|
||||
jsval_layout l;
|
||||
l.s.tag = JSVAL_TAG_MAGIC;
|
||||
l.s.payload.obj = obj;
|
||||
return l;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSBool
|
||||
JSVAL_SAME_TYPE_IMPL(jsval_layout lhs, jsval_layout rhs)
|
||||
{
|
||||
JSValueTag ltag = lhs.s.tag, rtag = rhs.s.tag;
|
||||
return ltag == rtag || (ltag < JSVAL_TAG_CLEAR && rtag < JSVAL_TAG_CLEAR);
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE jsval_layout
|
||||
PRIVATE_UINT32_TO_JSVAL_IMPL(uint32 ui)
|
||||
{
|
||||
jsval_layout l;
|
||||
l.s.tag = (JSValueTag)0;
|
||||
l.s.payload.u32 = ui;
|
||||
JS_ASSERT(JSVAL_IS_DOUBLE_IMPL(l));
|
||||
return l;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE uint32
|
||||
JSVAL_TO_PRIVATE_UINT32_IMPL(jsval_layout l)
|
||||
{
|
||||
return l.s.payload.u32;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSValueType
|
||||
JSVAL_EXTRACT_NON_DOUBLE_TYPE_IMPL(jsval_layout l)
|
||||
{
|
||||
uint32 type = l.s.tag & 0xF;
|
||||
JS_ASSERT(type > JSVAL_TYPE_DOUBLE);
|
||||
return (JSValueType)type;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSValueTag
|
||||
JSVAL_EXTRACT_NON_DOUBLE_TAG_IMPL(jsval_layout l)
|
||||
{
|
||||
JSValueTag tag = l.s.tag;
|
||||
JS_ASSERT(tag >= JSVAL_TAG_INT32);
|
||||
return tag;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
JS_STATIC_ASSERT((JSVAL_TYPE_NONFUNOBJ & 0xF) == JSVAL_TYPE_OBJECT);
|
||||
JS_STATIC_ASSERT((JSVAL_TYPE_FUNOBJ & 0xF) == JSVAL_TYPE_OBJECT);
|
||||
#endif
|
||||
|
||||
static JS_ALWAYS_INLINE jsval_layout
|
||||
BOX_NON_DOUBLE_JSVAL(JSValueType type, uint64 *slot)
|
||||
{
|
||||
jsval_layout l;
|
||||
JS_ASSERT(type > JSVAL_TYPE_DOUBLE && type <= JSVAL_UPPER_INCL_TYPE_OF_BOXABLE_SET);
|
||||
JS_ASSERT_IF(type == JSVAL_TYPE_STRING ||
|
||||
type == JSVAL_TYPE_OBJECT ||
|
||||
type == JSVAL_TYPE_NONFUNOBJ ||
|
||||
type == JSVAL_TYPE_FUNOBJ,
|
||||
*(uint32 *)slot != 0);
|
||||
l.s.tag = JSVAL_TYPE_TO_TAG(type & 0xF);
|
||||
/* A 32-bit value in a 64-bit slot always occupies the low-addressed end. */
|
||||
l.s.payload.u32 = *(uint32 *)slot;
|
||||
return l;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE void
|
||||
UNBOX_NON_DOUBLE_JSVAL(jsval_layout l, uint64 *out)
|
||||
{
|
||||
JS_ASSERT(!JSVAL_IS_DOUBLE_IMPL(l));
|
||||
*(uint32 *)out = l.s.payload.u32;
|
||||
}
|
||||
|
||||
#elif JS_BITS_PER_WORD == 64
|
||||
|
||||
static JS_ALWAYS_INLINE JSBool
|
||||
JSVAL_IS_SPECIFIC_INT32_IMPL(jsval_layout l, int32 i32)
|
||||
{
|
||||
return l.asBits == (((uint64)(uint32)i32) | JSVAL_SHIFTED_TAG_INT32);
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSBool
|
||||
JSVAL_IS_SPECIFIC_BOOLEAN(jsval_layout l, JSBool b)
|
||||
{
|
||||
return l.asBits == (((uint64)(uint32)b) | JSVAL_SHIFTED_TAG_BOOLEAN);
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE jsval_layout
|
||||
MAGIC_TO_JSVAL_IMPL(JSWhyMagic why)
|
||||
{
|
||||
jsval_layout l;
|
||||
l.asBits = ((uint64)(uint32)why) | JSVAL_SHIFTED_TAG_MAGIC;
|
||||
return l;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE jsval_layout
|
||||
MAGIC_TO_JSVAL_IMPL(JSObject *obj)
|
||||
{
|
||||
jsval_layout l;
|
||||
l.asBits = ((uint64)obj) | JSVAL_SHIFTED_TAG_MAGIC;
|
||||
return l;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSBool
|
||||
JSVAL_SAME_TYPE_IMPL(jsval_layout lhs, jsval_layout rhs)
|
||||
{
|
||||
uint64 lbits = lhs.asBits, rbits = rhs.asBits;
|
||||
return (lbits <= JSVAL_SHIFTED_TAG_MAX_DOUBLE && rbits <= JSVAL_SHIFTED_TAG_MAX_DOUBLE) ||
|
||||
(((lbits ^ rbits) & 0xFFFF800000000000LL) == 0);
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE jsval_layout
|
||||
PRIVATE_UINT32_TO_JSVAL_IMPL(uint32 ui)
|
||||
{
|
||||
jsval_layout l;
|
||||
l.asBits = (uint64)ui;
|
||||
JS_ASSERT(JSVAL_IS_DOUBLE_IMPL(l));
|
||||
return l;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE uint32
|
||||
JSVAL_TO_PRIVATE_UINT32_IMPL(jsval_layout l)
|
||||
{
|
||||
JS_ASSERT((l.asBits >> 32) == 0);
|
||||
return (uint32)l.asBits;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSValueType
|
||||
JSVAL_EXTRACT_NON_DOUBLE_TYPE_IMPL(jsval_layout l)
|
||||
{
|
||||
uint64 type = (l.asBits >> JSVAL_TAG_SHIFT) & 0xF;
|
||||
JS_ASSERT(type > JSVAL_TYPE_DOUBLE);
|
||||
return (JSValueType)type;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSValueTag
|
||||
JSVAL_EXTRACT_NON_DOUBLE_TAG_IMPL(jsval_layout l)
|
||||
{
|
||||
uint64 tag = l.asBits >> JSVAL_TAG_SHIFT;
|
||||
JS_ASSERT(tag > JSVAL_TAG_MAX_DOUBLE);
|
||||
return (JSValueTag)tag;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
JS_STATIC_ASSERT((JSVAL_TYPE_NONFUNOBJ & 0xF) == JSVAL_TYPE_OBJECT);
|
||||
JS_STATIC_ASSERT((JSVAL_TYPE_FUNOBJ & 0xF) == JSVAL_TYPE_OBJECT);
|
||||
#endif
|
||||
|
||||
static JS_ALWAYS_INLINE jsval_layout
|
||||
BOX_NON_DOUBLE_JSVAL(JSValueType type, uint64 *slot)
|
||||
{
|
||||
/* N.B. for 32-bit payloads, the high 32 bits of the slot are trash. */
|
||||
jsval_layout l;
|
||||
JS_ASSERT(type > JSVAL_TYPE_DOUBLE && type <= JSVAL_UPPER_INCL_TYPE_OF_BOXABLE_SET);
|
||||
uint32 isI32 = (uint32)(type < JSVAL_LOWER_INCL_TYPE_OF_PTR_PAYLOAD_SET);
|
||||
uint32 shift = isI32 * 32;
|
||||
uint64 mask = ((uint64)-1) >> shift;
|
||||
uint64 payload = *slot & mask;
|
||||
JS_ASSERT_IF(type == JSVAL_TYPE_STRING ||
|
||||
type == JSVAL_TYPE_OBJECT ||
|
||||
type == JSVAL_TYPE_NONFUNOBJ ||
|
||||
type == JSVAL_TYPE_FUNOBJ,
|
||||
payload != 0);
|
||||
l.asBits = payload | JSVAL_TYPE_TO_SHIFTED_TAG(type & 0xF);
|
||||
return l;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE void
|
||||
UNBOX_NON_DOUBLE_JSVAL(jsval_layout l, uint64 *out)
|
||||
{
|
||||
JS_ASSERT(!JSVAL_IS_DOUBLE_IMPL(l));
|
||||
*out = (l.asBits & JSVAL_PAYLOAD_MASK);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace js {
|
||||
|
||||
class Value
|
||||
{
|
||||
public:
|
||||
/*
|
||||
* N.B. the default constructor leaves Value unitialized. Adding a default
|
||||
* constructor prevents Value from being stored in a union.
|
||||
*/
|
||||
|
||||
/*** Mutatators ***/
|
||||
|
||||
JS_ALWAYS_INLINE
|
||||
void setNull() {
|
||||
data.asBits = JSVAL_BITS(JSVAL_NULL);
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE
|
||||
void setUndefined() {
|
||||
data.asBits = JSVAL_BITS(JSVAL_VOID);
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE
|
||||
void setInt32(int32 i) {
|
||||
data = INT32_TO_JSVAL_IMPL(i);
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE
|
||||
int32 &getInt32Ref() {
|
||||
JS_ASSERT(isInt32());
|
||||
return data.s.payload.i32;
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE
|
||||
void setDouble(double d) {
|
||||
data = DOUBLE_TO_JSVAL_IMPL(d);
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE
|
||||
double &getDoubleRef() {
|
||||
JS_ASSERT(isDouble());
|
||||
return data.asDouble;
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE
|
||||
void setString(JSString *str) {
|
||||
data = STRING_TO_JSVAL_IMPL(str);
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE
|
||||
void setString(const JS::Anchor<JSString *> &str) {
|
||||
setString(str.get());
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE
|
||||
void setObject(JSObject &obj) {
|
||||
data = OBJECT_TO_JSVAL_IMPL(&obj);
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE
|
||||
void setObject(const JS::Anchor<JSObject *> &obj) {
|
||||
setObject(*obj.get());
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE
|
||||
void setBoolean(bool b) {
|
||||
data = BOOLEAN_TO_JSVAL_IMPL(b);
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE
|
||||
void setMagic(JSWhyMagic why) {
|
||||
data = MAGIC_TO_JSVAL_IMPL(why);
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE
|
||||
void setMagicWithObjectOrNullPayload(JSObject *obj) {
|
||||
data = MAGIC_TO_JSVAL_IMPL(obj);
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE
|
||||
JSObject *getMagicObjectOrNullPayload() const {
|
||||
return MAGIC_JSVAL_TO_OBJECT_OR_NULL_IMPL(data);
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE
|
||||
bool setNumber(uint32 ui) {
|
||||
if (ui > JSVAL_INT_MAX) {
|
||||
setDouble((double)ui);
|
||||
return false;
|
||||
} else {
|
||||
setInt32((int32)ui);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE
|
||||
bool setNumber(double d) {
|
||||
int32_t i;
|
||||
if (JSDOUBLE_IS_INT32(d, &i)) {
|
||||
setInt32(i);
|
||||
return true;
|
||||
} else {
|
||||
setDouble(d);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE
|
||||
void setObjectOrNull(JSObject *arg) {
|
||||
if (arg)
|
||||
setObject(*arg);
|
||||
else
|
||||
setNull();
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE
|
||||
void setObjectOrUndefined(JSObject *arg) {
|
||||
if (arg)
|
||||
setObject(*arg);
|
||||
else
|
||||
setUndefined();
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE
|
||||
void swap(Value &rhs) {
|
||||
uint64 tmp = rhs.data.asBits;
|
||||
rhs.data.asBits = data.asBits;
|
||||
data.asBits = tmp;
|
||||
}
|
||||
|
||||
/*** Value type queries ***/
|
||||
|
||||
JS_ALWAYS_INLINE
|
||||
bool isUndefined() const {
|
||||
return JSVAL_IS_UNDEFINED_IMPL(data);
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE
|
||||
bool isNull() const {
|
||||
return JSVAL_IS_NULL_IMPL(data);
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE
|
||||
bool isNullOrUndefined() const {
|
||||
return isNull() || isUndefined();
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE
|
||||
bool isInt32() const {
|
||||
return JSVAL_IS_INT32_IMPL(data);
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE
|
||||
bool isInt32(int32 i32) const {
|
||||
return JSVAL_IS_SPECIFIC_INT32_IMPL(data, i32);
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE
|
||||
bool isDouble() const {
|
||||
return JSVAL_IS_DOUBLE_IMPL(data);
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE
|
||||
bool isNumber() const {
|
||||
return JSVAL_IS_NUMBER_IMPL(data);
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE
|
||||
bool isString() const {
|
||||
return JSVAL_IS_STRING_IMPL(data);
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE
|
||||
bool isObject() const {
|
||||
return JSVAL_IS_OBJECT_IMPL(data);
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE
|
||||
bool isPrimitive() const {
|
||||
return JSVAL_IS_PRIMITIVE_IMPL(data);
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE
|
||||
bool isObjectOrNull() const {
|
||||
return JSVAL_IS_OBJECT_OR_NULL_IMPL(data);
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE
|
||||
bool isGCThing() const {
|
||||
return JSVAL_IS_GCTHING_IMPL(data);
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE
|
||||
bool isBoolean() const {
|
||||
return JSVAL_IS_BOOLEAN_IMPL(data);
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE
|
||||
bool isTrue() const {
|
||||
return JSVAL_IS_SPECIFIC_BOOLEAN(data, true);
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE
|
||||
bool isFalse() const {
|
||||
return JSVAL_IS_SPECIFIC_BOOLEAN(data, false);
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE
|
||||
bool isMagic() const {
|
||||
return JSVAL_IS_MAGIC_IMPL(data);
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE
|
||||
bool isMagic(JSWhyMagic why) const {
|
||||
JS_ASSERT_IF(isMagic(), data.s.payload.why == why);
|
||||
return JSVAL_IS_MAGIC_IMPL(data);
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE
|
||||
bool isMagicCheck(JSWhyMagic why) const {
|
||||
return isMagic() && data.s.payload.why == why;
|
||||
}
|
||||
|
||||
#if JS_BITS_PER_WORD == 64
|
||||
JS_ALWAYS_INLINE
|
||||
bool hasPtrPayload() const {
|
||||
return data.asBits >= JSVAL_LOWER_INCL_SHIFTED_TAG_OF_PTR_PAYLOAD_SET;
|
||||
}
|
||||
#endif
|
||||
|
||||
JS_ALWAYS_INLINE
|
||||
bool isMarkable() const {
|
||||
return JSVAL_IS_TRACEABLE_IMPL(data);
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE
|
||||
JSGCTraceKind gcKind() const {
|
||||
JS_ASSERT(isMarkable());
|
||||
return JSGCTraceKind(JSVAL_TRACE_KIND_IMPL(data));
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE
|
||||
JSWhyMagic whyMagic() const {
|
||||
JS_ASSERT(isMagic());
|
||||
return data.s.payload.why;
|
||||
}
|
||||
|
||||
/*** Comparison ***/
|
||||
|
||||
JS_ALWAYS_INLINE
|
||||
bool operator==(const Value &rhs) const {
|
||||
return data.asBits == rhs.data.asBits;
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE
|
||||
bool operator!=(const Value &rhs) const {
|
||||
return data.asBits != rhs.data.asBits;
|
||||
}
|
||||
|
||||
/* This function used to be inlined here, but this triggered a gcc bug
|
||||
due to SameType being used in a template method.
|
||||
See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38850 */
|
||||
friend bool SameType(const Value &lhs, const Value &rhs);
|
||||
|
||||
/*** Extract the value's typed payload ***/
|
||||
|
||||
JS_ALWAYS_INLINE
|
||||
int32 toInt32() const {
|
||||
JS_ASSERT(isInt32());
|
||||
return JSVAL_TO_INT32_IMPL(data);
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE
|
||||
double toDouble() const {
|
||||
JS_ASSERT(isDouble());
|
||||
return data.asDouble;
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE
|
||||
double toNumber() const {
|
||||
JS_ASSERT(isNumber());
|
||||
return isDouble() ? toDouble() : double(toInt32());
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE
|
||||
JSString *toString() const {
|
||||
JS_ASSERT(isString());
|
||||
return JSVAL_TO_STRING_IMPL(data);
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE
|
||||
JSObject &toObject() const {
|
||||
JS_ASSERT(isObject());
|
||||
return *JSVAL_TO_OBJECT_IMPL(data);
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE
|
||||
JSObject *toObjectOrNull() const {
|
||||
JS_ASSERT(isObjectOrNull());
|
||||
return JSVAL_TO_OBJECT_IMPL(data);
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE
|
||||
void *toGCThing() const {
|
||||
JS_ASSERT(isGCThing());
|
||||
return JSVAL_TO_GCTHING_IMPL(data);
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE
|
||||
bool toBoolean() const {
|
||||
JS_ASSERT(isBoolean());
|
||||
return JSVAL_TO_BOOLEAN_IMPL(data);
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE
|
||||
uint32 payloadAsRawUint32() const {
|
||||
JS_ASSERT(!isDouble());
|
||||
return data.s.payload.u32;
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE
|
||||
uint64 asRawBits() const {
|
||||
return data.asBits;
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE
|
||||
void setRawBits(uint64 bits) {
|
||||
data.asBits = bits;
|
||||
}
|
||||
|
||||
/*
|
||||
* In the extract/box/unbox functions below, "NonDouble" means this
|
||||
* functions must not be called on a value that is a double. This allows
|
||||
* these operations to be implemented more efficiently, since doubles
|
||||
* generally already require special handling by the caller.
|
||||
*/
|
||||
JS_ALWAYS_INLINE
|
||||
JSValueType extractNonDoubleType() const {
|
||||
return JSVAL_EXTRACT_NON_DOUBLE_TYPE_IMPL(data);
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE
|
||||
JSValueTag extractNonDoubleTag() const {
|
||||
return JSVAL_EXTRACT_NON_DOUBLE_TAG_IMPL(data);
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE
|
||||
void unboxNonDoubleTo(uint64 *out) const {
|
||||
UNBOX_NON_DOUBLE_JSVAL(data, out);
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE
|
||||
void boxNonDoubleFrom(JSValueType type, uint64 *out) {
|
||||
data = BOX_NON_DOUBLE_JSVAL(type, out);
|
||||
}
|
||||
|
||||
/*
|
||||
* The trace-jit specializes JSVAL_TYPE_OBJECT into JSVAL_TYPE_FUNOBJ and
|
||||
* JSVAL_TYPE_NONFUNOBJ. Since these two operations just return the type of
|
||||
* a value, the caller must handle JSVAL_TYPE_OBJECT separately.
|
||||
*/
|
||||
JS_ALWAYS_INLINE
|
||||
JSValueType extractNonDoubleObjectTraceType() const {
|
||||
JS_ASSERT(!isObject());
|
||||
return JSVAL_EXTRACT_NON_DOUBLE_TYPE_IMPL(data);
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE
|
||||
JSValueTag extractNonDoubleObjectTraceTag() const {
|
||||
JS_ASSERT(!isObject());
|
||||
return JSVAL_EXTRACT_NON_DOUBLE_TAG_IMPL(data);
|
||||
}
|
||||
|
||||
/*
|
||||
* Private API
|
||||
*
|
||||
* Private setters/getters allow the caller to read/write arbitrary types
|
||||
* that fit in the 64-bit payload. It is the caller's responsibility, after
|
||||
* storing to a value with setPrivateX to read only using getPrivateX.
|
||||
* Privates values are given a type type which ensures they are not marked.
|
||||
*/
|
||||
|
||||
JS_ALWAYS_INLINE
|
||||
void setPrivate(void *ptr) {
|
||||
data = PRIVATE_PTR_TO_JSVAL_IMPL(ptr);
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE
|
||||
void *toPrivate() const {
|
||||
JS_ASSERT(JSVAL_IS_DOUBLE_IMPL(data));
|
||||
return JSVAL_TO_PRIVATE_PTR_IMPL(data);
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE
|
||||
void setPrivateUint32(uint32 ui) {
|
||||
data = PRIVATE_UINT32_TO_JSVAL_IMPL(ui);
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE
|
||||
uint32 toPrivateUint32() const {
|
||||
JS_ASSERT(JSVAL_IS_DOUBLE_IMPL(data));
|
||||
return JSVAL_TO_PRIVATE_UINT32_IMPL(data);
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE
|
||||
uint32 &getPrivateUint32Ref() {
|
||||
JS_ASSERT(isDouble());
|
||||
return data.s.payload.u32;
|
||||
}
|
||||
|
||||
/*
|
||||
* An unmarked value is just a void* cast as a Value. Thus, the Value is
|
||||
* not safe for GC and must not be marked. This API avoids raw casts
|
||||
* and the ensuing strict-aliasing warnings.
|
||||
*/
|
||||
|
||||
JS_ALWAYS_INLINE
|
||||
void setUnmarkedPtr(void *ptr) {
|
||||
data.asPtr = ptr;
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE
|
||||
void *toUnmarkedPtr() const {
|
||||
return data.asPtr;
|
||||
}
|
||||
|
||||
const jsuword *payloadWord() const {
|
||||
#if JS_BITS_PER_WORD == 32
|
||||
return &data.s.payload.word;
|
||||
#elif JS_BITS_PER_WORD == 64
|
||||
return &data.asWord;
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
void staticAssertions() {
|
||||
JS_STATIC_ASSERT(sizeof(JSValueType) == 1);
|
||||
JS_STATIC_ASSERT(sizeof(JSValueTag) == 4);
|
||||
JS_STATIC_ASSERT(sizeof(JSBool) == 4);
|
||||
JS_STATIC_ASSERT(sizeof(JSWhyMagic) <= 4);
|
||||
JS_STATIC_ASSERT(sizeof(jsval) == 8);
|
||||
}
|
||||
|
||||
jsval_layout data;
|
||||
} JSVAL_ALIGNMENT;
|
||||
|
||||
JS_ALWAYS_INLINE bool
|
||||
SameType(const Value &lhs, const Value &rhs)
|
||||
{
|
||||
return JSVAL_SAME_TYPE_IMPL(lhs.data, rhs.data);
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE Value
|
||||
NullValue()
|
||||
{
|
||||
Value v;
|
||||
v.setNull();
|
||||
return v;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE Value
|
||||
UndefinedValue()
|
||||
{
|
||||
Value v;
|
||||
v.setUndefined();
|
||||
return v;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE Value
|
||||
Int32Value(int32 i32)
|
||||
{
|
||||
Value v;
|
||||
v.setInt32(i32);
|
||||
return v;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE Value
|
||||
DoubleValue(double dbl)
|
||||
{
|
||||
Value v;
|
||||
v.setDouble(dbl);
|
||||
return v;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE Value
|
||||
StringValue(JSString *str)
|
||||
{
|
||||
Value v;
|
||||
v.setString(str);
|
||||
return v;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE Value
|
||||
BooleanValue(bool boo)
|
||||
{
|
||||
Value v;
|
||||
v.setBoolean(boo);
|
||||
return v;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE Value
|
||||
ObjectValue(JSObject &obj)
|
||||
{
|
||||
Value v;
|
||||
v.setObject(obj);
|
||||
return v;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE Value
|
||||
MagicValue(JSWhyMagic why)
|
||||
{
|
||||
Value v;
|
||||
v.setMagic(why);
|
||||
return v;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE Value
|
||||
NumberValue(double dbl)
|
||||
{
|
||||
Value v;
|
||||
v.setNumber(dbl);
|
||||
return v;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE Value
|
||||
ObjectOrNullValue(JSObject *obj)
|
||||
{
|
||||
Value v;
|
||||
v.setObjectOrNull(obj);
|
||||
return v;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE Value
|
||||
PrivateValue(void *ptr)
|
||||
{
|
||||
Value v;
|
||||
v.setPrivate(ptr);
|
||||
return v;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE Value
|
||||
PrivateUint32Value(uint32 ui)
|
||||
{
|
||||
Value v;
|
||||
v.setPrivateUint32(ui);
|
||||
return v;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE void
|
||||
ClearValueRange(Value *vec, uintN len, bool useHoles)
|
||||
{
|
||||
if (useHoles) {
|
||||
for (uintN i = 0; i < len; i++)
|
||||
vec[i].setMagic(JS_ARRAY_HOLE);
|
||||
} else {
|
||||
for (uintN i = 0; i < len; i++)
|
||||
vec[i].setUndefined();
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
/*
|
||||
* As asserted above, js::Value and jsval are layout equivalent. This means:
|
||||
* - an instance of jsval may be reinterpreted as a js::Value and vice versa;
|
||||
@ -915,15 +70,15 @@ ClearValueRange(Value *vec, uintN len, bool useHoles)
|
||||
* new safe overload to Jsvalify/Valueify.
|
||||
*/
|
||||
|
||||
static inline jsval * Jsvalify(Value *v) { return (jsval *)v; }
|
||||
static inline const jsval * Jsvalify(const Value *v) { return (const jsval *)v; }
|
||||
static inline jsval & Jsvalify(Value &v) { return (jsval &)v; }
|
||||
static inline const jsval & Jsvalify(const Value &v) { return (const jsval &)v; }
|
||||
static inline Value * Valueify(jsval *v) { return (Value *)v; }
|
||||
static inline const Value * Valueify(const jsval *v) { return (const Value *)v; }
|
||||
static inline Value ** Valueify(jsval **v) { return (Value **)v; }
|
||||
static inline Value & Valueify(jsval &v) { return (Value &)v; }
|
||||
static inline const Value & Valueify(const jsval &v) { return (const Value &)v; }
|
||||
static inline jsval * Jsvalify(Value *v) { return v; }
|
||||
static inline const jsval * Jsvalify(const Value *v) { return v; }
|
||||
static inline jsval & Jsvalify(Value &v) { return v; }
|
||||
static inline const jsval & Jsvalify(const Value &v) { return v; }
|
||||
static inline Value * Valueify(jsval *v) { return v; }
|
||||
static inline const Value * Valueify(const jsval *v) { return v; }
|
||||
static inline Value ** Valueify(jsval **v) { return v; }
|
||||
static inline Value & Valueify(jsval &v) { return v; }
|
||||
static inline const Value & Valueify(const jsval &v) { return v; }
|
||||
|
||||
struct Class;
|
||||
|
||||
@ -1163,10 +318,8 @@ static JS_ALWAYS_INLINE PropertyDescriptor * Valueify(JSPropertyDescriptor *p)
|
||||
# define JS_VALUEIFY(type, v) js::Valueify(v)
|
||||
# define JS_JSVALIFY(type, v) js::Jsvalify(v)
|
||||
|
||||
static inline JSNative JsvalifyNative(Native n) { return (JSNative) n; }
|
||||
static inline JSNative JsvalifyNative(JSNative n) { return n; }
|
||||
static inline Native ValueifyNative(JSNative n) { return (Native) n; }
|
||||
static inline Native ValueifyNative(Native n) { return n; }
|
||||
static inline JSNative JsvalifyNative(Native n) { return n; }
|
||||
static inline Native ValueifyNative(JSNative n) { return n; }
|
||||
static inline JSPropertyOp CastNativeToJSPropertyOp(Native n) { return (JSPropertyOp) n; }
|
||||
static inline JSStrictPropertyOp CastNativeToJSStrictPropertyOp(Native n) {
|
||||
return (JSStrictPropertyOp) n;
|
||||
@ -1243,6 +396,18 @@ ValueArgToConstRef(const Value &v)
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
static JS_ALWAYS_INLINE void
|
||||
ClearValueRange(Value *vec, uintN len, bool useHoles)
|
||||
{
|
||||
if (useHoles) {
|
||||
for (uintN i = 0; i < len; i++)
|
||||
vec[i].setMagic(JS_ARRAY_HOLE);
|
||||
} else {
|
||||
for (uintN i = 0; i < len; i++)
|
||||
vec[i].setUndefined();
|
||||
}
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE void
|
||||
MakeRangeGCSafe(Value *vec, size_t len)
|
||||
{
|
||||
|
@ -110,11 +110,6 @@ js_LeaveLocalRootScope(JSContext *cx)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void
|
||||
js_LeaveLocalRootScopeWithResult(JSContext *cx, jsval rval)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void
|
||||
js_LeaveLocalRootScopeWithResult(JSContext *cx, Value rval)
|
||||
{
|
||||
|
@ -70,9 +70,9 @@ class FrameEntry
|
||||
return v_;
|
||||
}
|
||||
|
||||
const Value &getValue() const {
|
||||
Value getValue() const {
|
||||
JS_ASSERT(isConstant());
|
||||
return Valueify(JSVAL_FROM_LAYOUT(v_));
|
||||
return IMPL_TO_JSVAL(v_);
|
||||
}
|
||||
|
||||
#if defined JS_NUNBOX32
|
||||
@ -212,18 +212,17 @@ class FrameEntry
|
||||
/*
|
||||
* Marks the FE as having a constant.
|
||||
*/
|
||||
void setConstant(const jsval &v) {
|
||||
void setConstant(const Value &v) {
|
||||
clear();
|
||||
type.unsync();
|
||||
data.unsync();
|
||||
type.setConstant();
|
||||
data.setConstant();
|
||||
v_.asBits = JSVAL_BITS(v);
|
||||
Value cv = Valueify(v);
|
||||
if (cv.isDouble())
|
||||
v_ = JSVAL_TO_IMPL(v);
|
||||
if (v.isDouble())
|
||||
knownType = JSVAL_TYPE_DOUBLE;
|
||||
else
|
||||
knownType = cv.extractNonDoubleType();
|
||||
knownType = v.extractNonDoubleType();
|
||||
}
|
||||
|
||||
FrameEntry *copyOf() const {
|
||||
|
@ -164,7 +164,7 @@ class NunboxAssembler : public JSC::MacroAssembler
|
||||
|
||||
void loadValueAsComponents(const Value &val, RegisterID type, RegisterID payload) {
|
||||
jsval_layout jv;
|
||||
jv.asBits = JSVAL_BITS(Jsvalify(val));
|
||||
jv.asBits = val.asRawBits();
|
||||
|
||||
move(ImmTag(jv.s.tag), type);
|
||||
move(Imm32(jv.s.payload.u32), payload);
|
||||
@ -172,7 +172,7 @@ class NunboxAssembler : public JSC::MacroAssembler
|
||||
|
||||
void loadValuePayload(const Value &val, RegisterID payload) {
|
||||
jsval_layout jv;
|
||||
jv.asBits = JSVAL_BITS(Jsvalify(val));
|
||||
jv.asBits = val.asRawBits();
|
||||
|
||||
move(Imm32(jv.s.payload.u32), payload);
|
||||
}
|
||||
@ -258,7 +258,7 @@ class NunboxAssembler : public JSC::MacroAssembler
|
||||
/* Overloaded for storing constant type and data. */
|
||||
DataLabel32 storeValueWithAddressOffsetPatch(const Value &v, Address address) {
|
||||
jsval_layout jv;
|
||||
jv.asBits = JSVAL_BITS(Jsvalify(v));
|
||||
jv.asBits = v.asRawBits();
|
||||
ImmTag type(jv.s.tag);
|
||||
Imm32 payload(jv.s.payload.u32);
|
||||
DataLabel32 start = dataLabel32();
|
||||
@ -297,7 +297,7 @@ class NunboxAssembler : public JSC::MacroAssembler
|
||||
template <typename T>
|
||||
Label storeValue(const Value &v, T address) {
|
||||
jsval_layout jv;
|
||||
jv.asBits = JSVAL_BITS(Jsvalify(v));
|
||||
jv.asBits = v.asRawBits();
|
||||
|
||||
store32(ImmTag(jv.s.tag), tagOf(address));
|
||||
Label l = label();
|
||||
|
@ -180,10 +180,7 @@ class PunboxAssembler : public JSC::MacroAssembler
|
||||
|
||||
/* Overload for constant type and constant data. */
|
||||
DataLabel32 storeValueWithAddressOffsetPatch(const Value &v, Address address) {
|
||||
jsval_layout jv;
|
||||
jv.asBits = JSVAL_BITS(Jsvalify(v));
|
||||
|
||||
move(ImmPtr(reinterpret_cast<void*>(jv.asBits)), Registers::ValueReg);
|
||||
move(ImmPtr(reinterpret_cast<void*>(v.asRawBits())), Registers::ValueReg);
|
||||
return storePtrWithAddressOffsetPatch(Registers::ValueReg, valueOf(address));
|
||||
}
|
||||
|
||||
@ -251,10 +248,7 @@ class PunboxAssembler : public JSC::MacroAssembler
|
||||
|
||||
template <typename T>
|
||||
void storeValue(const Value &v, T address) {
|
||||
jsval_layout jv;
|
||||
jv.asBits = JSVAL_BITS(Jsvalify(v));
|
||||
|
||||
storePtr(Imm64(jv.asBits), valueOf(address));
|
||||
storePtr(Imm64(v.asRawBits()), valueOf(address));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
@ -41,6 +41,7 @@
|
||||
#ifndef String_h_
|
||||
#define String_h_
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "jscell.h"
|
||||
|
||||
class JSString;
|
||||
|
@ -43,7 +43,7 @@
|
||||
#include "nsIException.idl"
|
||||
|
||||
%{ C++
|
||||
#include "jspubtd.h"
|
||||
#include "jsapi.h"
|
||||
%}
|
||||
|
||||
[ptr] native xpcexJSContextPtr(JSContext);
|
||||
|
@ -2957,7 +2957,7 @@ JS_EXPORT_API(void) DumpJSObject(JSObject* obj)
|
||||
|
||||
JS_EXPORT_API(void) DumpJSValue(jsval val)
|
||||
{
|
||||
printf("Dumping 0x%llu.\n", (long long) JSVAL_BITS(val));
|
||||
printf("Dumping 0x%llu.\n", (long long) val.asRawBits());
|
||||
if(JSVAL_IS_NULL(val)) {
|
||||
printf("Value is null\n");
|
||||
}
|
||||
|
@ -361,8 +361,7 @@ DefineGetterOrSetter(JSContext *cx, uintN argc, JSBool wantGetter, jsval *vp)
|
||||
JSObject *obj = JS_THIS_OBJECT(cx, vp);
|
||||
if (!obj)
|
||||
return JS_FALSE;
|
||||
JSNative forward = wantGetter ? Jsvalify(js_obj_defineGetter)
|
||||
: Jsvalify(js_obj_defineSetter);
|
||||
JSNative forward = wantGetter ? js_obj_defineGetter : js_obj_defineSetter;
|
||||
jsval idval = (argc >= 1) ? JS_ARGV(cx, vp)[0] : JSVAL_VOID;
|
||||
if(!JSVAL_IS_STRING(idval))
|
||||
return forward(cx, argc, vp);
|
||||
|
@ -253,7 +253,7 @@ Variant_base::GetAsWStringWithSize(PRUint32 *,
|
||||
|
||||
inline
|
||||
NS_IMETHODIMP
|
||||
Variant_base::GetAsJSVal(jsval *)
|
||||
Variant_base::GetAsJSVal(JS::Value *)
|
||||
{
|
||||
return NS_ERROR_CANNOT_CONVERT_DATA;
|
||||
}
|
||||
|
@ -1887,7 +1887,7 @@ NS_IMETHODIMP nsVariant::GetAsISupports(nsISupports **_retval)
|
||||
}
|
||||
|
||||
/* jsval getAsJSVal() */
|
||||
NS_IMETHODIMP nsVariant::GetAsJSVal(jsval *_retval)
|
||||
NS_IMETHODIMP nsVariant::GetAsJSVal(JS::Value *_retval)
|
||||
{
|
||||
// Can only get the jsval from an XPCVariant.
|
||||
return NS_ERROR_CANNOT_CONVERT_DATA;
|
||||
|
@ -417,7 +417,7 @@ class Native(object):
|
||||
'utf8string': 'nsACString',
|
||||
'cstring': 'nsACString',
|
||||
'astring': 'nsAString',
|
||||
'jsval': 'jsval'
|
||||
'jsval': 'JS::Value'
|
||||
}
|
||||
|
||||
def __init__(self, name, nativename, attlist, location):
|
||||
|
Loading…
Reference in New Issue
Block a user