Bug 684526 - Unify jsval and js::Value (r=jorendorff)

--HG--
extra : rebase_source : 5655602775d575bb5adba0a8fc4c20621f393a67
This commit is contained in:
Luke Wagner 2011-09-19 09:34:49 -07:00
parent 5a81c92645
commit cc2ce861d1
32 changed files with 1695 additions and 1742 deletions

View File

@ -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"

View File

@ -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

View File

@ -41,7 +41,7 @@
#include "Workers.h"
#include "jspubtd.h"
#include "jsapi.h"
#include "prclist.h"
BEGIN_WORKERS_NAMESPACE

View File

@ -41,7 +41,7 @@
#include "Workers.h"
#include "jspubtd.h"
#include "jsapi.h"
BEGIN_WORKERS_NAMESPACE

View File

@ -41,7 +41,7 @@
#include "Workers.h"
#include "jspubtd.h"
#include "jsapi.h"
BEGIN_WORKERS_NAMESPACE

View File

@ -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);

View File

@ -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);

File diff suppressed because it is too large Load Diff

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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

View File

@ -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);
}

View File

@ -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. */

View File

@ -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;

View File

@ -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 {

View File

@ -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___ */

View File

@ -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

View File

@ -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:

View File

@ -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__ */

View File

@ -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)
{

View File

@ -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)
{

View File

@ -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 {

View File

@ -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();

View File

@ -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>

View File

@ -41,6 +41,7 @@
#ifndef String_h_
#define String_h_
#include "jsapi.h"
#include "jscell.h"
class JSString;

View File

@ -43,7 +43,7 @@
#include "nsIException.idl"
%{ C++
#include "jspubtd.h"
#include "jsapi.h"
%}
[ptr] native xpcexJSContextPtr(JSContext);

View File

@ -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");
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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;

View File

@ -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):