зеркало из https://github.com/mozilla/pjs.git
Merge tracemonkey to mozilla-central.
This commit is contained in:
Коммит
c5b2bbeb04
|
@ -3101,10 +3101,10 @@ nsXULPrototypeScript::Compile(const PRUnichar* aText,
|
|||
//
|
||||
// Compiling it using (for example) the first document's global
|
||||
// object would cause JS to keep a reference via the __proto__ or
|
||||
// __parent__ pointer to the first document's global. If that
|
||||
// happened, our script object would reference the first document,
|
||||
// and the first document would indirectly reference the prototype
|
||||
// document because it keeps the prototype cache alive. Circularity!
|
||||
// parent pointer to the first document's global. If that happened,
|
||||
// our script object would reference the first document, and the
|
||||
// first document would indirectly reference the prototype document
|
||||
// because it keeps the prototype cache alive. Circularity!
|
||||
nsresult rv;
|
||||
|
||||
// Use the prototype document's special context
|
||||
|
|
|
@ -1266,3 +1266,65 @@ nsDOMWindowUtils::GetVisitedDependentComputedStyle(
|
|||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWindowUtils::GetParent()
|
||||
{
|
||||
// This wasn't privileged in the past, but better to expose less than more.
|
||||
if (!IsUniversalXPConnectCapable()) {
|
||||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIXPConnect> xpc = nsContentUtils::XPConnect();
|
||||
|
||||
// get the xpconnect native call context
|
||||
nsAXPCNativeCallContext *cc = nsnull;
|
||||
xpc->GetCurrentNativeCallContext(&cc);
|
||||
if(!cc)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// Get JSContext of current call
|
||||
JSContext* cx;
|
||||
nsresult rv = cc->GetJSContext(&cx);
|
||||
if(NS_FAILED(rv) || !cx)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// get place for return value
|
||||
jsval *rval = nsnull;
|
||||
rv = cc->GetRetValPtr(&rval);
|
||||
if(NS_FAILED(rv) || !rval)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// get argc and argv and verify arg count
|
||||
PRUint32 argc;
|
||||
rv = cc->GetArgc(&argc);
|
||||
if(NS_FAILED(rv))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if(argc != 1)
|
||||
return NS_ERROR_XPC_NOT_ENOUGH_ARGS;
|
||||
|
||||
jsval* argv;
|
||||
rv = cc->GetArgvPtr(&argv);
|
||||
if(NS_FAILED(rv) || !argv)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// first argument must be an object
|
||||
if(JSVAL_IS_PRIMITIVE(argv[0]))
|
||||
return NS_ERROR_XPC_BAD_CONVERT_JS;
|
||||
|
||||
JSObject *parent = JS_GetParent(cx, JSVAL_TO_OBJECT(argv[0]));
|
||||
*rval = OBJECT_TO_JSVAL(parent);
|
||||
|
||||
// Outerize if necessary. Embrace the ugliness!
|
||||
JSClass *clasp = JS_GetClass(cx, parent);
|
||||
if (clasp->flags & JSCLASS_IS_EXTENDED) {
|
||||
JSExtendedClass *xclasp = reinterpret_cast<JSExtendedClass *>(clasp);
|
||||
if (JSObjectOp outerize = xclasp->outerObject)
|
||||
*rval = OBJECT_TO_JSVAL(outerize(cx, parent));
|
||||
}
|
||||
|
||||
cc->SetReturnValueWasSet(PR_TRUE);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -53,7 +53,7 @@ interface nsIDOMEvent;
|
|||
interface nsITransferable;
|
||||
interface nsIQueryContentEventResult;
|
||||
|
||||
[scriptable, uuid(22a62b54-bcf5-422a-a329-fed4de5e78b2)]
|
||||
[scriptable, uuid(352ff0af-bb38-496a-a067-b54771168d6d)]
|
||||
interface nsIDOMWindowUtils : nsISupports {
|
||||
|
||||
/**
|
||||
|
@ -655,4 +655,12 @@ interface nsIDOMWindowUtils : nsISupports {
|
|||
AString getVisitedDependentComputedStyle(in nsIDOMElement aElement,
|
||||
in AString aPseudoElement,
|
||||
in AString aPropertyName);
|
||||
|
||||
/**
|
||||
* Returns the parent of obj.
|
||||
*
|
||||
* @param obj The JavaScript object whose parent is to be gotten.
|
||||
* @return the parent.
|
||||
*/
|
||||
void getParent(/* obj */);
|
||||
};
|
||||
|
|
|
@ -77,21 +77,6 @@ function inspect(obj) {
|
|||
return;
|
||||
}
|
||||
print("* Object type: "+typeof obj+"\n");
|
||||
if (typeof obj != "xml") {
|
||||
print("* Parent chain: ");
|
||||
try {
|
||||
var parent = obj.__parent__;
|
||||
while(parent) {
|
||||
try {
|
||||
print(parent);
|
||||
}
|
||||
catch(e) { dump("(?)"); }
|
||||
finally { dump(" "); }
|
||||
parent = parent.__parent__;
|
||||
}
|
||||
} catch(e) { dump("...(?)"); }
|
||||
print("\n");
|
||||
}
|
||||
switch(typeof obj) {
|
||||
case "object":
|
||||
print("* Prototype chain: ");
|
||||
|
|
|
@ -3946,16 +3946,18 @@ StructType::DefineInternal(JSContext* cx, JSObject* typeObj, JSObject* fieldsObj
|
|||
// Create a hash of FieldInfo objects to stash on the type object.
|
||||
FieldInfoHash* fields(new FieldInfoHash);
|
||||
if (!fields || !fields->init(len)) {
|
||||
delete fields;
|
||||
JS_ReportOutOfMemory(cx);
|
||||
delete fields;
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
// Stash the FieldInfo hash in a reserved slot now, for GC safety of its
|
||||
// constituents.
|
||||
if (!JS_SetReservedSlot(cx, typeObj, SLOT_FIELDINFO,
|
||||
PRIVATE_TO_JSVAL(fields)))
|
||||
PRIVATE_TO_JSVAL(fields))) {
|
||||
delete fields;
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
// Process the field types.
|
||||
size_t structSize, structAlign;
|
||||
|
|
|
@ -1345,7 +1345,6 @@ static JSStdName standard_class_names[] = {
|
|||
static JSStdName object_prototype_names[] = {
|
||||
/* Object.prototype properties (global delegates to Object.prototype). */
|
||||
{js_InitObjectClass, EAGER_ATOM(proto), NULL},
|
||||
{js_InitObjectClass, EAGER_ATOM(parent), NULL},
|
||||
#if JS_HAS_TOSOURCE
|
||||
{js_InitObjectClass, EAGER_ATOM(toSource), NULL},
|
||||
#endif
|
||||
|
@ -4237,12 +4236,11 @@ js_generic_fast_native_method_dispatcher(JSContext *cx, uintN argc, jsval *vp)
|
|||
fs = (JSFunctionSpec *) JSVAL_TO_PRIVATE(fsv);
|
||||
JS_ASSERT((~fs->flags & (JSFUN_FAST_NATIVE | JSFUN_GENERIC_NATIVE)) == 0);
|
||||
|
||||
/*
|
||||
* We know that vp[2] is valid because JS_DefineFunctions, which is our
|
||||
* only (indirect) referrer, defined us as requiring at least one argument
|
||||
* (notice how it passes fs->nargs + 1 as the next-to-last argument to
|
||||
* JS_DefineFunction).
|
||||
*/
|
||||
if (argc < 1) {
|
||||
js_ReportMissingArg(cx, vp, 0);
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
if (JSVAL_IS_PRIMITIVE(vp[2])) {
|
||||
/*
|
||||
* Make sure that this is an object or null, as required by the generic
|
||||
|
@ -4267,15 +4265,9 @@ js_generic_fast_native_method_dispatcher(JSContext *cx, uintN argc, jsval *vp)
|
|||
*/
|
||||
if (!js_ComputeThis(cx, vp + 2))
|
||||
return JS_FALSE;
|
||||
/*
|
||||
* Protect against argc underflowing. By calling js_ComputeThis, we made
|
||||
* it as if the static was called with one parameter, the explicit |this|
|
||||
* object.
|
||||
*/
|
||||
if (argc != 0) {
|
||||
/* Clear the last parameter in case too few arguments were passed. */
|
||||
vp[2 + --argc] = JSVAL_VOID;
|
||||
}
|
||||
|
||||
/* Clear the last parameter in case too few arguments were passed. */
|
||||
vp[2 + --argc] = JSVAL_VOID;
|
||||
|
||||
native =
|
||||
#ifdef JS_TRACER
|
||||
|
@ -4301,12 +4293,11 @@ js_generic_native_method_dispatcher(JSContext *cx, JSObject *obj,
|
|||
JS_ASSERT((fs->flags & (JSFUN_FAST_NATIVE | JSFUN_GENERIC_NATIVE)) ==
|
||||
JSFUN_GENERIC_NATIVE);
|
||||
|
||||
/*
|
||||
* We know that argv[0] is valid because JS_DefineFunctions, which is our
|
||||
* only (indirect) referrer, defined us as requiring at least one argument
|
||||
* (notice how it passes fs->nargs + 1 as the next-to-last argument to
|
||||
* JS_DefineFunction).
|
||||
*/
|
||||
if (argc < 1) {
|
||||
js_ReportMissingArg(cx, argv - 2, 0);
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
if (JSVAL_IS_PRIMITIVE(argv[0])) {
|
||||
/*
|
||||
* Make sure that this is an object or null, as required by the generic
|
||||
|
@ -4334,15 +4325,8 @@ js_generic_native_method_dispatcher(JSContext *cx, JSObject *obj,
|
|||
js_GetTopStackFrame(cx)->thisv = argv[-1];
|
||||
JS_ASSERT(cx->fp->argv == argv);
|
||||
|
||||
/*
|
||||
* Protect against argc underflowing. By calling js_ComputeThis, we made
|
||||
* it as if the static was called with one parameter, the explicit |this|
|
||||
* object.
|
||||
*/
|
||||
if (argc != 0) {
|
||||
/* Clear the last parameter in case too few arguments were passed. */
|
||||
argv[--argc] = JSVAL_VOID;
|
||||
}
|
||||
/* Clear the last parameter in case too few arguments were passed. */
|
||||
argv[--argc] = JSVAL_VOID;
|
||||
|
||||
return fs->call(cx, JSVAL_TO_OBJECT(argv[-1]), argc, argv, rval);
|
||||
}
|
||||
|
|
|
@ -57,7 +57,8 @@
|
|||
* setters, it's updated automatically by setDenseArrayLength() and
|
||||
* setDenseArrayCapacity(). There are also no explicit getters, the only
|
||||
* user is TraceRecorder which can access it directly because it's a
|
||||
* friend.
|
||||
* friend. The function isDenseArrayMinLenCapOk() checks that it is set
|
||||
* correctly; a call to it should be put in an assertion at use points.
|
||||
*
|
||||
* In dense mode, holes in the array are represented by JSVAL_HOLE. The final
|
||||
* slot in fslots is unused.
|
||||
|
@ -1273,8 +1274,7 @@ JSClass js_ArrayClass = {
|
|||
"Array",
|
||||
JSCLASS_HAS_RESERVED_SLOTS(2) |
|
||||
JSCLASS_HAS_CACHED_PROTO(JSProto_Array) |
|
||||
JSCLASS_NEW_ENUMERATE |
|
||||
JSCLASS_CONSTRUCT_PROTOTYPE,
|
||||
JSCLASS_NEW_ENUMERATE,
|
||||
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
|
||||
JS_EnumerateStub, JS_ResolveStub, js_TryValueOf, array_finalize,
|
||||
array_getObjectOps, NULL, NULL, NULL,
|
||||
|
|
|
@ -147,7 +147,6 @@ const char *const js_common_atom_names[] = {
|
|||
js_name_str, /* nameAtom */
|
||||
js_next_str, /* nextAtom */
|
||||
js_noSuchMethod_str, /* noSuchMethodAtom */
|
||||
js_parent_str, /* parentAtom */
|
||||
js_proto_str, /* protoAtom */
|
||||
js_set_str, /* setAtom */
|
||||
js_stack_str, /* stackAtom */
|
||||
|
@ -220,7 +219,6 @@ const char js_name_str[] = "name";
|
|||
const char js_next_str[] = "next";
|
||||
const char js_noSuchMethod_str[] = "__noSuchMethod__";
|
||||
const char js_object_str[] = "object";
|
||||
const char js_parent_str[] = "__parent__";
|
||||
const char js_proto_str[] = "__proto__";
|
||||
const char js_setter_str[] = "setter";
|
||||
const char js_set_str[] = "set";
|
||||
|
|
|
@ -259,7 +259,6 @@ struct JSAtomState {
|
|||
JSAtom *nameAtom;
|
||||
JSAtom *nextAtom;
|
||||
JSAtom *noSuchMethodAtom;
|
||||
JSAtom *parentAtom;
|
||||
JSAtom *protoAtom;
|
||||
JSAtom *setAtom;
|
||||
JSAtom *stackAtom;
|
||||
|
@ -388,7 +387,6 @@ extern const char js_namespace_str[];
|
|||
extern const char js_next_str[];
|
||||
extern const char js_noSuchMethod_str[];
|
||||
extern const char js_object_str[];
|
||||
extern const char js_parent_str[];
|
||||
extern const char js_proto_str[];
|
||||
extern const char js_ptagc_str[];
|
||||
extern const char js_qualifier_str[];
|
||||
|
|
|
@ -832,10 +832,9 @@ struct JSRuntime {
|
|||
void *gcExtraRootsData;
|
||||
|
||||
/*
|
||||
* Used to serialize cycle checks when setting __proto__ or __parent__ by
|
||||
* requesting the GC handle the required cycle detection. If the GC hasn't
|
||||
* been poked, it won't scan for garbage. This member is protected by
|
||||
* rt->gcLock.
|
||||
* Used to serialize cycle checks when setting __proto__ by requesting the
|
||||
* GC handle the required cycle detection. If the GC hasn't been poked, it
|
||||
* won't scan for garbage. This member is protected by rt->gcLock.
|
||||
*/
|
||||
JSSetSlotRequest *setSlotRequests;
|
||||
|
||||
|
|
|
@ -49,15 +49,14 @@
|
|||
|
||||
#define TYPEOF(cx,v) (JSVAL_IS_NULL(v) ? JSTYPE_NULL : JS_TypeOfValue(cx,v))
|
||||
|
||||
using namespace js;
|
||||
|
||||
static char dempty[] = "<null>";
|
||||
|
||||
static char *
|
||||
jsdtrace_fun_classname(const JSFunction *fun)
|
||||
{
|
||||
return (fun &&
|
||||
!FUN_INTERPRETED(fun) &&
|
||||
!(fun->flags & JSFUN_TRCINFO) &&
|
||||
FUN_CLASP(fun))
|
||||
return (fun && !FUN_INTERPRETED(fun) && !(fun->flags & JSFUN_TRCINFO) && FUN_CLASP(fun))
|
||||
? (char *)FUN_CLASP(fun)->name
|
||||
: dempty;
|
||||
}
|
||||
|
@ -65,9 +64,7 @@ jsdtrace_fun_classname(const JSFunction *fun)
|
|||
static char *
|
||||
jsdtrace_filename(JSStackFrame *fp)
|
||||
{
|
||||
return (fp && fp->script && fp->script->filename)
|
||||
? (char *)fp->script->filename
|
||||
: dempty;
|
||||
return (fp && fp->script && fp->script->filename) ? (char *)fp->script->filename : dempty;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -79,7 +76,7 @@ jsdtrace_fun_linenumber(JSContext *cx, const JSFunction *fun)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
jsdtrace_frame_linenumber(JSContext *cx, JSStackFrame *fp)
|
||||
{
|
||||
if (fp && fp->regs)
|
||||
|
@ -138,13 +135,10 @@ jsdtrace_jsvaltovoid(JSContext *cx, const jsval argval)
|
|||
static char *
|
||||
jsdtrace_fun_name(JSContext *cx, const JSFunction *fun)
|
||||
{
|
||||
JSAtom *atom;
|
||||
char *name;
|
||||
|
||||
if (!fun)
|
||||
return dempty;
|
||||
|
||||
atom = fun->atom;
|
||||
JSAtom *atom = fun->atom;
|
||||
if (!atom) {
|
||||
/*
|
||||
* TODO: maybe do more work here to figure out the name of the property
|
||||
|
@ -154,7 +148,7 @@ jsdtrace_fun_name(JSContext *cx, const JSFunction *fun)
|
|||
return dempty;
|
||||
}
|
||||
|
||||
name = (char *)js_GetStringBytes(cx, ATOM_TO_STRING(atom));
|
||||
char *name = (char *)js_GetStringBytes(cx, ATOM_TO_STRING(atom));
|
||||
return name ? name : dempty;
|
||||
}
|
||||
|
||||
|
@ -166,117 +160,85 @@ jsdtrace_fun_name(JSContext *cx, const JSFunction *fun)
|
|||
* a number of usually unused lines of code would cause.
|
||||
*/
|
||||
void
|
||||
jsdtrace_function_entry(JSContext *cx, JSStackFrame *fp, const JSFunction *fun)
|
||||
DTrace::enterJSFunImpl(JSContext *cx, JSStackFrame *fp, const JSFunction *fun)
|
||||
{
|
||||
JAVASCRIPT_FUNCTION_ENTRY(
|
||||
jsdtrace_filename(fp),
|
||||
jsdtrace_fun_classname(fun),
|
||||
jsdtrace_fun_name(cx, fun)
|
||||
);
|
||||
JAVASCRIPT_FUNCTION_ENTRY(jsdtrace_filename(fp), jsdtrace_fun_classname(fun),
|
||||
jsdtrace_fun_name(cx, fun));
|
||||
}
|
||||
|
||||
void
|
||||
jsdtrace_function_info(JSContext *cx, JSStackFrame *fp, JSStackFrame *dfp,
|
||||
JSFunction *fun)
|
||||
DTrace::handleFunctionInfo(JSContext *cx, JSStackFrame *fp, JSStackFrame *dfp, JSFunction *fun)
|
||||
{
|
||||
JAVASCRIPT_FUNCTION_INFO(
|
||||
jsdtrace_filename(fp),
|
||||
jsdtrace_fun_classname(fun),
|
||||
jsdtrace_fun_name(cx, fun),
|
||||
jsdtrace_fun_linenumber(cx, fun),
|
||||
jsdtrace_filename(dfp),
|
||||
jsdtrace_frame_linenumber(cx, dfp)
|
||||
);
|
||||
JAVASCRIPT_FUNCTION_INFO(jsdtrace_filename(fp), jsdtrace_fun_classname(fun),
|
||||
jsdtrace_fun_name(cx, fun), jsdtrace_fun_linenumber(cx, fun),
|
||||
jsdtrace_filename(dfp), jsdtrace_frame_linenumber(cx, dfp));
|
||||
}
|
||||
|
||||
void
|
||||
jsdtrace_function_args(JSContext *cx, JSStackFrame *fp, const JSFunction *fun,
|
||||
jsuint argc, jsval *argv)
|
||||
DTrace::handleFunctionArgs(JSContext *cx, JSStackFrame *fp, const JSFunction *fun, jsuint argc,
|
||||
jsval *argv)
|
||||
{
|
||||
JAVASCRIPT_FUNCTION_ARGS(
|
||||
jsdtrace_filename(fp),
|
||||
jsdtrace_fun_classname(fun),
|
||||
jsdtrace_fun_name(cx, fun),
|
||||
argc, (void *)argv,
|
||||
(argc > 0) ? jsdtrace_jsvaltovoid(cx, argv[0]) : 0,
|
||||
(argc > 1) ? jsdtrace_jsvaltovoid(cx, argv[1]) : 0,
|
||||
(argc > 2) ? jsdtrace_jsvaltovoid(cx, argv[2]) : 0,
|
||||
(argc > 3) ? jsdtrace_jsvaltovoid(cx, argv[3]) : 0,
|
||||
(argc > 4) ? jsdtrace_jsvaltovoid(cx, argv[4]) : 0
|
||||
);
|
||||
JAVASCRIPT_FUNCTION_ARGS(jsdtrace_filename(fp), jsdtrace_fun_classname(fun),
|
||||
jsdtrace_fun_name(cx, fun), argc, (void *)argv,
|
||||
(argc > 0) ? jsdtrace_jsvaltovoid(cx, argv[0]) : 0,
|
||||
(argc > 1) ? jsdtrace_jsvaltovoid(cx, argv[1]) : 0,
|
||||
(argc > 2) ? jsdtrace_jsvaltovoid(cx, argv[2]) : 0,
|
||||
(argc > 3) ? jsdtrace_jsvaltovoid(cx, argv[3]) : 0,
|
||||
(argc > 4) ? jsdtrace_jsvaltovoid(cx, argv[4]) : 0);
|
||||
}
|
||||
|
||||
void
|
||||
jsdtrace_function_rval(JSContext *cx, JSStackFrame *fp, JSFunction *fun, jsval *rval)
|
||||
DTrace::handleFunctionRval(JSContext *cx, JSStackFrame *fp, JSFunction *fun, jsval rval)
|
||||
{
|
||||
JAVASCRIPT_FUNCTION_RVAL(
|
||||
jsdtrace_filename(fp),
|
||||
jsdtrace_fun_classname(fun),
|
||||
jsdtrace_fun_name(cx, fun),
|
||||
jsdtrace_fun_linenumber(cx, fun),
|
||||
(void *)rval,
|
||||
jsdtrace_jsvaltovoid(cx, *rval)
|
||||
);
|
||||
JAVASCRIPT_FUNCTION_RVAL(jsdtrace_filename(fp), jsdtrace_fun_classname(fun),
|
||||
jsdtrace_fun_name(cx, fun), jsdtrace_fun_linenumber(cx, fun),
|
||||
NULL, jsdtrace_jsvaltovoid(cx, rval));
|
||||
}
|
||||
|
||||
void
|
||||
jsdtrace_function_return(JSContext *cx, JSStackFrame *fp, JSFunction *fun)
|
||||
DTrace::handleFunctionReturn(JSContext *cx, JSStackFrame *fp, JSFunction *fun)
|
||||
{
|
||||
JAVASCRIPT_FUNCTION_RETURN(
|
||||
jsdtrace_filename(fp),
|
||||
jsdtrace_fun_classname(fun),
|
||||
jsdtrace_fun_name(cx, fun)
|
||||
);
|
||||
JAVASCRIPT_FUNCTION_RETURN(jsdtrace_filename(fp), jsdtrace_fun_classname(fun),
|
||||
jsdtrace_fun_name(cx, fun));
|
||||
}
|
||||
|
||||
void
|
||||
jsdtrace_object_create_start(JSStackFrame *fp, JSClass *clasp)
|
||||
DTrace::ObjectCreationScope::handleCreationStart()
|
||||
{
|
||||
JAVASCRIPT_OBJECT_CREATE_START(jsdtrace_filename(fp), (char *)clasp->name);
|
||||
}
|
||||
|
||||
void
|
||||
jsdtrace_object_create_done(JSStackFrame *fp, JSClass *clasp)
|
||||
DTrace::ObjectCreationScope::handleCreationEnd()
|
||||
{
|
||||
JAVASCRIPT_OBJECT_CREATE_DONE(jsdtrace_filename(fp), (char *)clasp->name);
|
||||
}
|
||||
|
||||
void
|
||||
jsdtrace_object_create(JSContext *cx, JSClass *clasp, JSObject *obj)
|
||||
DTrace::ObjectCreationScope::handleCreationImpl(JSObject *obj)
|
||||
{
|
||||
JAVASCRIPT_OBJECT_CREATE(
|
||||
jsdtrace_filename(cx->fp),
|
||||
(char *)clasp->name,
|
||||
(uintptr_t)obj,
|
||||
jsdtrace_frame_linenumber(cx, cx->fp)
|
||||
);
|
||||
JAVASCRIPT_OBJECT_CREATE(jsdtrace_filename(cx->fp), (char *)clasp->name, (uintptr_t)obj,
|
||||
jsdtrace_frame_linenumber(cx, cx->fp));
|
||||
}
|
||||
|
||||
void
|
||||
jsdtrace_object_finalize(JSObject *obj)
|
||||
DTrace::finalizeObjectImpl(JSObject *obj)
|
||||
{
|
||||
JSClass *clasp;
|
||||
|
||||
clasp = obj->getClass();
|
||||
JSClass *clasp = obj->getClass();
|
||||
|
||||
/* the first arg is NULL - reserved for future use (filename?) */
|
||||
JAVASCRIPT_OBJECT_FINALIZE(NULL, (char *)clasp->name, (uintptr_t)obj);
|
||||
}
|
||||
|
||||
void
|
||||
jsdtrace_execute_start(JSScript *script)
|
||||
DTrace::ExecutionScope::startExecution()
|
||||
{
|
||||
JAVASCRIPT_EXECUTE_START(
|
||||
script->filename ? (char *)script->filename : dempty,
|
||||
script->lineno
|
||||
);
|
||||
JAVASCRIPT_EXECUTE_START(script->filename ? (char *)script->filename : dempty,
|
||||
script->lineno);
|
||||
}
|
||||
|
||||
void
|
||||
jsdtrace_execute_done(JSScript *script)
|
||||
DTrace::ExecutionScope::endExecution()
|
||||
{
|
||||
JAVASCRIPT_EXECUTE_DONE(
|
||||
script->filename ? (char *)script->filename : dempty,
|
||||
script->lineno
|
||||
);
|
||||
JAVASCRIPT_EXECUTE_DONE(script->filename ? (char *)script->filename : dempty, script->lineno);
|
||||
}
|
||||
|
|
|
@ -42,126 +42,139 @@
|
|||
#ifndef _JSDTRACEF_H
|
||||
#define _JSDTRACEF_H
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
extern void
|
||||
jsdtrace_function_entry(JSContext *cx, JSStackFrame *fp, const JSFunction *fun);
|
||||
|
||||
extern void
|
||||
jsdtrace_function_info(JSContext *cx, JSStackFrame *fp, JSStackFrame *dfp,
|
||||
const JSFunction *fun);
|
||||
|
||||
extern void
|
||||
jsdtrace_function_args(JSContext *cx, JSStackFrame *fp, const JSFunction *fun,
|
||||
jsuint argc, jsval *argv);
|
||||
|
||||
extern void
|
||||
jsdtrace_function_rval(JSContext *cx, JSStackFrame *fp, const JSFunction *fun,
|
||||
jsval rval);
|
||||
|
||||
extern void
|
||||
jsdtrace_function_return(JSContext *cx, JSStackFrame *fp, const JSFunction *fun);
|
||||
|
||||
extern void
|
||||
jsdtrace_object_create_start(JSStackFrame *fp, const JSClass *clasp);
|
||||
|
||||
extern void
|
||||
jsdtrace_object_create_done(JSStackFrame *fp, const JSClass *clasp);
|
||||
|
||||
extern void
|
||||
jsdtrace_object_create(JSContext *cx, const JSClass *clasp, const JSObject *obj);
|
||||
|
||||
extern void
|
||||
jsdtrace_object_finalize(const JSObject *obj);
|
||||
|
||||
extern void
|
||||
jsdtrace_execute_start(const JSScript *script);
|
||||
|
||||
extern void
|
||||
jsdtrace_execute_done(const JSScript *script);
|
||||
|
||||
JS_END_EXTERN_C
|
||||
|
||||
namespace js {
|
||||
|
||||
class DTrace {
|
||||
static void enterJSFunImpl(JSContext *cx, JSStackFrame *fp, const JSFunction *fun);
|
||||
static void handleFunctionInfo(JSContext *cx, JSStackFrame *fp, JSStackFrame *dfp,
|
||||
JSFunction *fun);
|
||||
static void handleFunctionArgs(JSContext *cx, JSStackFrame *fp, const JSFunction *fun,
|
||||
jsuint argc, jsval *argv);
|
||||
static void handleFunctionRval(JSContext *cx, JSStackFrame *fp, JSFunction *fun, jsval rval);
|
||||
static void handleFunctionReturn(JSContext *cx, JSStackFrame *fp, JSFunction *fun);
|
||||
static void finalizeObjectImpl(JSObject *obj);
|
||||
public:
|
||||
/*
|
||||
* If |lval| is provided to the enter/exit methods, it is tested to see if
|
||||
* it is a function as a predicate to the dtrace event emission.
|
||||
*/
|
||||
static void enterJSFun(JSContext *cx, JSStackFrame *fp, const JSFunction *fun,
|
||||
static void enterJSFun(JSContext *cx, JSStackFrame *fp, JSFunction *fun,
|
||||
JSStackFrame *dfp, jsuint argc, jsval *argv, jsval *lval = NULL);
|
||||
static void exitJSFun(JSContext *cx, JSStackFrame *fp, const JSFunction *fun,
|
||||
jsval rval, jsval *lval = NULL);
|
||||
static void exitJSFun(JSContext *cx, JSStackFrame *fp, JSFunction *fun, jsval rval,
|
||||
jsval *lval = NULL);
|
||||
|
||||
static void finalizeObject(const JSObject *obj);
|
||||
static void finalizeObject(JSObject *obj);
|
||||
|
||||
class ExecutionScope {
|
||||
const JSScript *script;
|
||||
void startExecution();
|
||||
void endExecution();
|
||||
public:
|
||||
explicit ExecutionScope(const JSScript *script) : script(script) { startExecution(); }
|
||||
~ExecutionScope() { endExecution(); }
|
||||
explicit ExecutionScope(JSScript *script);
|
||||
~ExecutionScope();
|
||||
};
|
||||
|
||||
class ObjectCreationScope {
|
||||
JSContext * const cx;
|
||||
JSStackFrame * const fp;
|
||||
JSClass * const clasp;
|
||||
void handleCreationStart();
|
||||
void handleCreationImpl(JSObject *obj);
|
||||
void handleCreationEnd();
|
||||
public:
|
||||
ObjectCreationScope(JSContext *cx, JSStackFrame *fp, JSClass *clasp);
|
||||
void handleCreation(JSObject *obj);
|
||||
~ObjectCreationScope();
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
inline void
|
||||
DTrace::enterJSFun(JSContext *cx, JSStackFrame *fp, const JSFunction *fun,
|
||||
JSStackFrame *dfp, jsuint argc, jsval *argv, jsval *lval)
|
||||
DTrace::enterJSFun(JSContext *cx, JSStackFrame *fp, JSFunction *fun, JSStackFrame *dfp,
|
||||
jsuint argc, jsval *argv, jsval *lval)
|
||||
{
|
||||
#ifdef INCLUDE_MOZILLA_DTRACE
|
||||
if (!lval || VALUE_IS_FUNCTION(cx, *lval)) {
|
||||
if (JAVASCRIPT_FUNCTION_ENTRY_ENABLED())
|
||||
jsdtrace_function_entry(cx, fp, fun);
|
||||
enterJSFunImpl(cx, fp, fun);
|
||||
if (JAVASCRIPT_FUNCTION_INFO_ENABLED())
|
||||
jsdtrace_function_info(cx, fp, dfp, fun);
|
||||
handleFunctionInfo(cx, fp, dfp, fun);
|
||||
if (JAVASCRIPT_FUNCTION_ARGS_ENABLED())
|
||||
jsdtrace_function_args(cx, fp, fun, argc, argv);
|
||||
handleFunctionArgs(cx, fp, fun, argc, argv);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void
|
||||
DTrace::exitJSFun(JSContext *cx, JSStackFrame *fp, const JSFunction *fun,
|
||||
jsval rval, jsval *lval)
|
||||
DTrace::exitJSFun(JSContext *cx, JSStackFrame *fp, JSFunction *fun, jsval rval, jsval *lval)
|
||||
{
|
||||
#ifdef INCLUDE_MOZILLA_DTRACE
|
||||
if (!lval || VALUE_IS_FUNCTION(cx, *lval)) {
|
||||
if (JAVASCRIPT_FUNCTION_RVAL_ENABLED())
|
||||
jsdtrace_function_rval(cx, fp, fun, rval);
|
||||
handleFunctionRval(cx, fp, fun, rval);
|
||||
if (JAVASCRIPT_FUNCTION_RETURN_ENABLED())
|
||||
jsdtrace_function_return(cx, fp, fun);
|
||||
handleFunctionReturn(cx, fp, fun);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void
|
||||
DTrace::finalizeObject(const JSObject *obj)
|
||||
DTrace::finalizeObject(JSObject *obj)
|
||||
{
|
||||
#ifdef INCLUDE_MOZILLA_DTRACE
|
||||
if (JAVASCRIPT_OBJECT_FINALIZE_ENABLED())
|
||||
jsdtrace_object_finalize(obj);
|
||||
finalizeObjectImpl(obj);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void
|
||||
DTrace::ExecutionScope::startExecution()
|
||||
/* Execution scope. */
|
||||
|
||||
inline
|
||||
DTrace::ExecutionScope::ExecutionScope(JSScript *script)
|
||||
: script(script)
|
||||
{
|
||||
#ifdef INCLUDE_MOZILLA_DTRACE
|
||||
if (JAVASCRIPT_EXECUTE_START_ENABLED())
|
||||
jsdtrace_execute_start(script);
|
||||
startExecution();
|
||||
#endif
|
||||
}
|
||||
|
||||
inline
|
||||
DTrace::ExecutionScope::~ExecutionScope()
|
||||
{
|
||||
#ifdef INCLUDE_MOZILLA_DTRACE
|
||||
if (JAVASCRIPT_EXECUTE_DONE_ENABLED())
|
||||
endExecution();
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Object creation scope. */
|
||||
|
||||
inline
|
||||
DTrace::ObjectCreationScope::ObjectCreationScope(JSContext *cx, JSStackFrame *fp, JSClass *clasp)
|
||||
: cx(cx), fp(fp), clasp(clasp)
|
||||
{
|
||||
#ifdef INCLUDE_MOZILLA_DTRACE
|
||||
if (JAVASCRIPT_OBJECT_CREATE_START_ENABLED())
|
||||
handleCreationStart();
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void
|
||||
DTrace::ExecutionScope::endExecution()
|
||||
DTrace::ObjectCreationScope::handleCreation(JSObject *obj)
|
||||
{
|
||||
#ifdef INCLUDE_MOZILLA_DTRACE
|
||||
if (JAVASCRIPT_EXECUTE_DONE_ENABLED())
|
||||
jsdtrace_execute_done(script);
|
||||
if (JAVASCRIPT_OBJECT_CREATE_ENABLED())
|
||||
handleCreationImpl(obj);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline
|
||||
DTrace::ObjectCreationScope::~ObjectCreationScope()
|
||||
{
|
||||
#ifdef INCLUDE_MOZILLA_DTRACE
|
||||
if (JAVASCRIPT_OBJECT_CREATE_DONE_ENABLED())
|
||||
handleCreationEnd();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -1882,7 +1882,7 @@ EmitEnterBlock(JSContext *cx, JSParseNode *pn, JSCodeGenerator *cg)
|
|||
}
|
||||
|
||||
blockObj->scope()->freeslot = JSSLOT_FREE(&js_BlockClass);
|
||||
return js_GrowSlots(cx, blockObj, JSSLOT_FREE(&js_BlockClass));
|
||||
return blockObj->growSlots(cx, JSSLOT_FREE(&js_BlockClass));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2688,10 +2688,9 @@ static JSBool
|
|||
EmitSpecialPropOp(JSContext *cx, JSParseNode *pn, JSOp op, JSCodeGenerator *cg)
|
||||
{
|
||||
/*
|
||||
* Special case for obj.__proto__ and obj.__parent__ to deoptimize away
|
||||
* from fast paths in the interpreter and trace recorder, which skip dense
|
||||
* array instances by going up to Array.prototype before looking up the
|
||||
* property name.
|
||||
* Special case for obj.__proto__ to deoptimize away from fast paths in the
|
||||
* interpreter and trace recorder, which skip dense array instances by
|
||||
* going up to Array.prototype before looking up the property name.
|
||||
*/
|
||||
JSAtomListElement *ale = cg->atomList.add(cg->parser, pn->pn_atom);
|
||||
if (!ale)
|
||||
|
@ -2713,10 +2712,9 @@ EmitPropOp(JSContext *cx, JSParseNode *pn, JSOp op, JSCodeGenerator *cg,
|
|||
JS_ASSERT(pn->pn_arity == PN_NAME);
|
||||
pn2 = pn->maybeExpr();
|
||||
|
||||
/* Special case deoptimization on __proto__ and __parent__. */
|
||||
/* Special case deoptimization for __proto__. */
|
||||
if ((op == JSOP_GETPROP || op == JSOP_CALLPROP) &&
|
||||
(pn->pn_atom == cx->runtime->atomState.protoAtom ||
|
||||
pn->pn_atom == cx->runtime->atomState.parentAtom)) {
|
||||
pn->pn_atom == cx->runtime->atomState.protoAtom) {
|
||||
if (pn2 && !js_EmitTree(cx, cg, pn2))
|
||||
return JS_FALSE;
|
||||
return EmitSpecialPropOp(cx, pn, callContext ? JSOP_CALLELEM : JSOP_GETELEM, cg);
|
||||
|
@ -2802,13 +2800,8 @@ EmitPropOp(JSContext *cx, JSParseNode *pn, JSOp op, JSCodeGenerator *cg,
|
|||
return JS_FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Special case deoptimization on __proto__ and __parent__, as
|
||||
* above.
|
||||
*/
|
||||
if (pndot->pn_arity == PN_NAME &&
|
||||
(pndot->pn_atom == cx->runtime->atomState.protoAtom ||
|
||||
pndot->pn_atom == cx->runtime->atomState.parentAtom)) {
|
||||
/* Special case deoptimization on __proto__, as above. */
|
||||
if (pndot->pn_arity == PN_NAME && pndot->pn_atom == cx->runtime->atomState.protoAtom) {
|
||||
if (!EmitSpecialPropOp(cx, pndot, JSOP_GETELEM, cg))
|
||||
return JS_FALSE;
|
||||
} else if (!EmitAtomOp(cx, pndot, PN_OP(pndot), cg)) {
|
||||
|
@ -7409,9 +7402,8 @@ js_FinishTakingTryNotes(JSCodeGenerator *cg, JSTryNoteArray *array)
|
|||
*
|
||||
* In such cases, naively following ECMA leads to wrongful sharing of RegExp
|
||||
* objects, which makes for collisions on the lastIndex property (especially
|
||||
* for global regexps) and on any ad-hoc properties. Also, __proto__ and
|
||||
* __parent__ refer to the pre-compilation prototype and global objects, a
|
||||
* pigeon-hole problem for instanceof tests.
|
||||
* for global regexps) and on any ad-hoc properties. Also, __proto__ refers to
|
||||
* the pre-compilation prototype, a pigeon-hole problem for instanceof tests.
|
||||
*/
|
||||
uintN
|
||||
JSCGObjectList::index(JSObjectBox *objbox)
|
||||
|
|
|
@ -576,9 +576,8 @@ ArgSetter(JSContext *cx, JSObject *obj, jsval idval, jsval *vp)
|
|||
* args_delete to clear the corresponding reserved slot so the GC can
|
||||
* collect its value.
|
||||
*/
|
||||
jsid id;
|
||||
if (!JS_ValueToId(cx, idval, &id))
|
||||
return false;
|
||||
JS_ASSERT_IF(JSVAL_IS_STRING(idval), JSVAL_TO_STRING(idval)->isAtomized());
|
||||
jsid id = (jsid)idval;
|
||||
|
||||
AutoValueRooter tvr(cx);
|
||||
return js_DeleteProperty(cx, obj, id, tvr.addr()) &&
|
||||
|
@ -1151,7 +1150,6 @@ call_resolve(JSContext *cx, JSObject *obj, jsval idval, uintN flags,
|
|||
{
|
||||
jsval callee;
|
||||
JSFunction *fun;
|
||||
jsid id;
|
||||
JSLocalKind localKind;
|
||||
JSPropertyOp getter, setter;
|
||||
uintN slot, attrs;
|
||||
|
@ -1162,14 +1160,14 @@ call_resolve(JSContext *cx, JSObject *obj, jsval idval, uintN flags,
|
|||
if (!JSVAL_IS_STRING(idval))
|
||||
return JS_TRUE;
|
||||
|
||||
JS_ASSERT(JSVAL_TO_STRING(idval)->isAtomized());
|
||||
jsid id = (jsval)idval;
|
||||
|
||||
callee = obj->getSlot(JSSLOT_CALLEE);
|
||||
if (JSVAL_IS_VOID(callee))
|
||||
return JS_TRUE;
|
||||
fun = GET_FUNCTION_PRIVATE(cx, JSVAL_TO_OBJECT(callee));
|
||||
|
||||
if (!js_ValueToStringId(cx, idval, &id))
|
||||
return JS_FALSE;
|
||||
|
||||
/*
|
||||
* Check whether the id refers to a formal parameter, local variable or
|
||||
* the arguments special name.
|
||||
|
|
|
@ -1559,6 +1559,8 @@ js_TraceOpcode(JSContext *cx)
|
|||
(n == -ndefs) ? " output:" : ",",
|
||||
bytes);
|
||||
cx->free(bytes);
|
||||
} else {
|
||||
JS_ClearPendingException(cx);
|
||||
}
|
||||
}
|
||||
fprintf(tracefp, " @ %u\n", (uintN) (regs->sp - StackBase(fp)));
|
||||
|
@ -1566,10 +1568,12 @@ js_TraceOpcode(JSContext *cx)
|
|||
fprintf(tracefp, " stack: ");
|
||||
for (siter = StackBase(fp); siter < regs->sp; siter++) {
|
||||
str = js_ValueToString(cx, *siter);
|
||||
if (!str)
|
||||
if (!str) {
|
||||
fputs("<null>", tracefp);
|
||||
else
|
||||
} else {
|
||||
JS_ClearPendingException(cx);
|
||||
js_FileEscapedString(tracefp, str, 0);
|
||||
}
|
||||
fputc(' ', tracefp);
|
||||
}
|
||||
fputc('\n', tracefp);
|
||||
|
@ -1591,6 +1595,8 @@ js_TraceOpcode(JSContext *cx)
|
|||
(n == -nuses) ? " inputs:" : ",",
|
||||
bytes);
|
||||
cx->free(bytes);
|
||||
} else {
|
||||
JS_ClearPendingException(cx);
|
||||
}
|
||||
}
|
||||
fprintf(tracefp, " @ %u\n", (uintN) (regs->sp - StackBase(fp)));
|
||||
|
|
202
js/src/jsobj.cpp
202
js/src/jsobj.cpp
|
@ -126,59 +126,29 @@ JSClass js_ObjectClass = {
|
|||
#if JS_HAS_OBJ_PROTO_PROP
|
||||
|
||||
static JSBool
|
||||
obj_getSlot(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
|
||||
obj_getProto(JSContext *cx, JSObject *obj, jsid id, jsval *vp);
|
||||
|
||||
static JSBool
|
||||
obj_setSlot(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
|
||||
obj_setProto(JSContext *cx, JSObject *obj, jsid id, jsval *vp);
|
||||
|
||||
static JSPropertySpec object_props[] = {
|
||||
/* These two must come first; see object_props[slot].name usage below. */
|
||||
{js_proto_str, JSSLOT_PROTO, JSPROP_PERMANENT|JSPROP_SHARED,
|
||||
obj_getSlot, obj_setSlot},
|
||||
{js_parent_str,JSSLOT_PARENT,JSPROP_READONLY|JSPROP_PERMANENT|JSPROP_SHARED,
|
||||
obj_getSlot, obj_setSlot},
|
||||
{js_proto_str, JSSLOT_PROTO, JSPROP_PERMANENT|JSPROP_SHARED, obj_getProto, obj_setProto},
|
||||
{0,0,0,0,0}
|
||||
};
|
||||
|
||||
/* NB: JSSLOT_PROTO and JSSLOT_PARENT are already indexes into object_props. */
|
||||
#define JSSLOT_COUNT 2
|
||||
|
||||
static JSBool
|
||||
ReportStrictSlot(JSContext *cx, uint32 slot)
|
||||
obj_getProto(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
|
||||
{
|
||||
if (slot == JSSLOT_PROTO)
|
||||
return JS_TRUE;
|
||||
return JS_ReportErrorFlagsAndNumber(cx,
|
||||
JSREPORT_WARNING | JSREPORT_STRICT,
|
||||
js_GetErrorMessage, NULL,
|
||||
JSMSG_DEPRECATED_USAGE,
|
||||
object_props[slot].name);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
obj_getSlot(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
||||
{
|
||||
jsid propid;
|
||||
JSAccessMode mode;
|
||||
uintN attrs;
|
||||
JSObject *pobj;
|
||||
JSClass *clasp;
|
||||
|
||||
if (id == INT_TO_JSVAL(JSSLOT_PROTO)) {
|
||||
propid = ATOM_TO_JSID(cx->runtime->atomState.protoAtom);
|
||||
mode = JSACC_PROTO;
|
||||
} else {
|
||||
propid = ATOM_TO_JSID(cx->runtime->atomState.parentAtom);
|
||||
mode = JSACC_PARENT;
|
||||
}
|
||||
JS_ASSERT(id == INT_TO_JSID(JSSLOT_PROTO));
|
||||
|
||||
/* Let obj->checkAccess get the slot's value, based on the access mode. */
|
||||
if (!obj->checkAccess(cx, propid, mode, vp, &attrs))
|
||||
uintN attrs;
|
||||
id = ATOM_TO_JSID(cx->runtime->atomState.protoAtom);
|
||||
if (!obj->checkAccess(cx, id, JSACC_PROTO, vp, &attrs))
|
||||
return JS_FALSE;
|
||||
|
||||
pobj = JSVAL_TO_OBJECT(*vp);
|
||||
if (pobj) {
|
||||
clasp = pobj->getClass();
|
||||
if (JSObject *pobj = JSVAL_TO_OBJECT(*vp)) {
|
||||
JSClass *clasp = pobj->getClass();
|
||||
if (clasp == &js_CallClass || clasp == &js_BlockClass) {
|
||||
/* Censor activations and lexical scopes per ECMA-262. */
|
||||
*vp = JSVAL_NULL;
|
||||
|
@ -188,8 +158,8 @@ obj_getSlot(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
|||
* censor. So it cannot escape to scripts.
|
||||
*/
|
||||
JS_ASSERT(clasp != &js_DeclEnvClass);
|
||||
if (pobj->map->ops->thisObject) {
|
||||
pobj = pobj->map->ops->thisObject(cx, pobj);
|
||||
if (JSObjectOp thisObject = pobj->map->ops->thisObject) {
|
||||
pobj = thisObject(cx, pobj);
|
||||
if (!pobj)
|
||||
return JS_FALSE;
|
||||
*vp = OBJECT_TO_JSVAL(pobj);
|
||||
|
@ -200,17 +170,14 @@ obj_getSlot(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
|||
}
|
||||
|
||||
static JSBool
|
||||
obj_setSlot(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
||||
obj_setProto(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
|
||||
{
|
||||
JSObject *pobj;
|
||||
uint32 slot;
|
||||
jsid propid;
|
||||
uintN attrs;
|
||||
JS_ASSERT(id == INT_TO_JSID(JSSLOT_PROTO));
|
||||
|
||||
if (!JSVAL_IS_OBJECT(*vp))
|
||||
return JS_TRUE;
|
||||
pobj = JSVAL_TO_OBJECT(*vp);
|
||||
|
||||
JSObject *pobj = JSVAL_TO_OBJECT(*vp);
|
||||
if (pobj) {
|
||||
/*
|
||||
* Innerize pobj here to avoid sticking unwanted properties on the
|
||||
|
@ -221,16 +188,13 @@ obj_setSlot(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
|||
if (!pobj)
|
||||
return JS_FALSE;
|
||||
}
|
||||
slot = (uint32) JSVAL_TO_INT(id);
|
||||
if (JS_HAS_STRICT_OPTION(cx) && !ReportStrictSlot(cx, slot))
|
||||
|
||||
uintN attrs;
|
||||
id = ATOM_TO_JSID(cx->runtime->atomState.protoAtom);
|
||||
if (!obj->checkAccess(cx, id, JSAccessMode(JSACC_PROTO|JSACC_WRITE), vp, &attrs))
|
||||
return JS_FALSE;
|
||||
|
||||
/* __parent__ is readonly and permanent, only __proto__ may be set. */
|
||||
propid = ATOM_TO_JSID(cx->runtime->atomState.protoAtom);
|
||||
if (!obj->checkAccess(cx, propid, (JSAccessMode)(JSACC_PROTO|JSACC_WRITE), vp, &attrs))
|
||||
return JS_FALSE;
|
||||
|
||||
return js_SetProtoOrParent(cx, obj, slot, pobj, JS_TRUE);
|
||||
return js_SetProtoOrParent(cx, obj, JSSLOT_PROTO, pobj, JS_TRUE);
|
||||
}
|
||||
|
||||
#else /* !JS_HAS_OBJ_PROTO_PROP */
|
||||
|
@ -300,15 +264,8 @@ js_SetProtoOrParent(JSContext *cx, JSObject *obj, uint32 slot, JSObject *pobj,
|
|||
}
|
||||
|
||||
if (ssr.cycle) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
||||
JSMSG_CYCLIC_VALUE,
|
||||
#if JS_HAS_OBJ_PROTO_PROP
|
||||
object_props[slot].name
|
||||
#else
|
||||
(slot == JSSLOT_PROTO) ? js_proto_str
|
||||
: js_parent_str
|
||||
#endif
|
||||
);
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CYCLIC_VALUE,
|
||||
(slot == JSSLOT_PROTO) ? js_proto_str : "parent");
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
|
@ -1951,13 +1908,12 @@ obj_keys(JSContext *cx, uintN argc, jsval *vp)
|
|||
return JS_FALSE;
|
||||
*vp = OBJECT_TO_JSVAL(aobj);
|
||||
|
||||
jsval *slots = aobj->dslots;
|
||||
size_t len = ida.length();
|
||||
JS_ASSERT(aobj->getDenseArrayCapacity() >= len);
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
jsid id = ida[i];
|
||||
if (JSID_IS_INT(id)) {
|
||||
if (!js_ValueToStringId(cx, INT_JSID_TO_JSVAL(id), &slots[i]))
|
||||
if (!js_ValueToStringId(cx, INT_JSID_TO_JSVAL(id), aobj->addressOfDenseArrayElement(i)))
|
||||
return JS_FALSE;
|
||||
} else {
|
||||
/*
|
||||
|
@ -1967,7 +1923,7 @@ obj_keys(JSContext *cx, uintN argc, jsval *vp)
|
|||
* to by a QName, actually appears as a string jsid -- but in the
|
||||
* interests of fidelity we pass object jsids through unchanged.
|
||||
*/
|
||||
slots[i] = ID_TO_VALUE(id);
|
||||
aobj->setDenseArrayElement(i, ID_TO_VALUE(id));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3137,7 +3093,7 @@ js_PutBlockObject(JSContext *cx, JSBool normalUnwind)
|
|||
if (normalUnwind && count > 1) {
|
||||
--count;
|
||||
JS_LOCK_OBJ(cx, obj);
|
||||
if (!js_AllocSlots(cx, obj, JS_INITIAL_NSLOTS + count))
|
||||
if (!obj->allocSlots(cx, JS_INITIAL_NSLOTS + count))
|
||||
normalUnwind = JS_FALSE;
|
||||
else
|
||||
memcpy(obj->dslots, fp->slots + depth + 1, count * sizeof(jsval));
|
||||
|
@ -3521,35 +3477,28 @@ bad:
|
|||
goto out;
|
||||
}
|
||||
|
||||
#define SLOTS_TO_DYNAMIC_WORDS(nslots) \
|
||||
(JS_ASSERT((nslots) > JS_INITIAL_NSLOTS), (nslots) + 1 - JS_INITIAL_NSLOTS)
|
||||
|
||||
#define DYNAMIC_WORDS_TO_SLOTS(words) \
|
||||
(JS_ASSERT((words) > 1), (words) - 1 + JS_INITIAL_NSLOTS)
|
||||
|
||||
|
||||
bool
|
||||
js_AllocSlots(JSContext *cx, JSObject *obj, size_t nslots)
|
||||
JSObject::allocSlots(JSContext *cx, size_t nslots)
|
||||
{
|
||||
JS_ASSERT(!obj->dslots);
|
||||
JS_ASSERT(!dslots);
|
||||
JS_ASSERT(nslots > JS_INITIAL_NSLOTS);
|
||||
|
||||
jsval* slots;
|
||||
slots = (jsval*) cx->malloc(SLOTS_TO_DYNAMIC_WORDS(nslots) * sizeof(jsval));
|
||||
if (!slots)
|
||||
size_t nwords = slotsToDynamicWords(nslots);
|
||||
dslots = (jsval*) cx->malloc(nwords * sizeof(jsval));
|
||||
if (!dslots)
|
||||
return false;
|
||||
|
||||
*slots++ = nslots;
|
||||
dslots++;
|
||||
dslots[-1] = nslots;
|
||||
/* clear the newly allocated cells. */
|
||||
for (jsuint n = JS_INITIAL_NSLOTS; n < nslots; ++n)
|
||||
slots[n - JS_INITIAL_NSLOTS] = JSVAL_VOID;
|
||||
obj->dslots = slots;
|
||||
for (jsuint i = JS_INITIAL_NSLOTS; i < nslots; i++)
|
||||
dslots[i - JS_INITIAL_NSLOTS] = JSVAL_VOID;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
js_GrowSlots(JSContext *cx, JSObject *obj, size_t nslots)
|
||||
JSObject::growSlots(JSContext *cx, size_t nslots)
|
||||
{
|
||||
/*
|
||||
* Minimal number of dynamic slots to allocate.
|
||||
|
@ -3566,7 +3515,7 @@ js_GrowSlots(JSContext *cx, JSObject *obj, size_t nslots)
|
|||
if (nslots <= JS_INITIAL_NSLOTS)
|
||||
return JS_TRUE;
|
||||
|
||||
size_t nwords = SLOTS_TO_DYNAMIC_WORDS(nslots);
|
||||
size_t nwords = slotsToDynamicWords(nslots);
|
||||
|
||||
/*
|
||||
* Round up nslots so the number of bytes in dslots array is power
|
||||
|
@ -3581,55 +3530,55 @@ js_GrowSlots(JSContext *cx, JSObject *obj, size_t nslots)
|
|||
} else {
|
||||
nwords = JS_ROUNDUP(nwords, LINEAR_GROWTH_STEP);
|
||||
}
|
||||
nslots = DYNAMIC_WORDS_TO_SLOTS(nwords);
|
||||
nslots = dynamicWordsToSlots(nwords);
|
||||
|
||||
/*
|
||||
* If nothing was allocated yet, treat it as initial allocation (but with
|
||||
* the exponential growth algorithm applied).
|
||||
*/
|
||||
jsval* slots = obj->dslots;
|
||||
if (!slots)
|
||||
return js_AllocSlots(cx, obj, nslots);
|
||||
if (!dslots)
|
||||
return allocSlots(cx, nslots);
|
||||
|
||||
size_t oslots = size_t(slots[-1]);
|
||||
size_t oldnslots = size_t(dslots[-1]);
|
||||
|
||||
slots = (jsval*) cx->realloc(slots - 1, nwords * sizeof(jsval));
|
||||
if (!slots)
|
||||
return false;
|
||||
jsval *tmpdslots = (jsval*) cx->realloc(dslots - 1, nwords * sizeof(jsval));
|
||||
if (!tmpdslots)
|
||||
return false; /* Leave dslots at its old size. */
|
||||
dslots = tmpdslots;
|
||||
|
||||
*slots++ = nslots;
|
||||
obj->dslots = slots;
|
||||
dslots++;
|
||||
dslots[-1] = nslots;
|
||||
|
||||
/* Initialize the additional slots we added. */
|
||||
JS_ASSERT(nslots > oslots);
|
||||
for (size_t i = oslots; i < nslots; i++)
|
||||
slots[i - JS_INITIAL_NSLOTS] = JSVAL_VOID;
|
||||
JS_ASSERT(nslots > oldnslots);
|
||||
for (size_t i = oldnslots; i < nslots; i++)
|
||||
dslots[i - JS_INITIAL_NSLOTS] = JSVAL_VOID;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
js_ShrinkSlots(JSContext *cx, JSObject *obj, size_t nslots)
|
||||
JSObject::shrinkSlots(JSContext *cx, size_t nslots)
|
||||
{
|
||||
jsval* slots = obj->dslots;
|
||||
|
||||
/* Nothing to shrink? */
|
||||
if (!slots)
|
||||
if (!dslots)
|
||||
return;
|
||||
|
||||
JS_ASSERT(size_t(slots[-1]) > JS_INITIAL_NSLOTS);
|
||||
JS_ASSERT(nslots <= size_t(slots[-1]));
|
||||
JS_ASSERT(size_t(dslots[-1]) > JS_INITIAL_NSLOTS);
|
||||
JS_ASSERT(nslots <= size_t(dslots[-1]));
|
||||
|
||||
if (nslots <= JS_INITIAL_NSLOTS) {
|
||||
obj->freeSlotsArray(cx);
|
||||
obj->dslots = NULL;
|
||||
freeSlotsArray(cx);
|
||||
dslots = NULL;
|
||||
} else {
|
||||
size_t nwords = SLOTS_TO_DYNAMIC_WORDS(nslots);
|
||||
slots = (jsval*) cx->realloc(slots - 1, nwords * sizeof(jsval));
|
||||
if (!slots)
|
||||
return; /* Leave obj->dslots at its old size. */
|
||||
*slots++ = nslots;
|
||||
obj->dslots = slots;
|
||||
size_t nwords = slotsToDynamicWords(nslots);
|
||||
jsval *tmpdslots = (jsval*) cx->realloc(dslots - 1, nwords * sizeof(jsval));
|
||||
if (!tmpdslots)
|
||||
return; /* Leave dslots at its old size. */
|
||||
dslots = tmpdslots;
|
||||
|
||||
dslots++;
|
||||
dslots[-1] = nslots;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3637,10 +3586,9 @@ bool
|
|||
js_EnsureReservedSlots(JSContext *cx, JSObject *obj, size_t nreserved)
|
||||
{
|
||||
JS_ASSERT(obj->isNative());
|
||||
JS_ASSERT(!obj->dslots);
|
||||
|
||||
uintN nslots = JSSLOT_FREE(obj->getClass()) + nreserved;
|
||||
if (nslots > obj->numSlots() && !js_AllocSlots(cx, obj, nslots))
|
||||
if (nslots > obj->numSlots() && !obj->allocSlots(cx, nslots))
|
||||
return false;
|
||||
|
||||
JSScope *scope = obj->scope();
|
||||
|
@ -3839,8 +3787,8 @@ js_ConstructObject(JSContext *cx, JSClass *clasp, JSObject *proto,
|
|||
AutoValueRooter tvr(cx, cval);
|
||||
|
||||
/*
|
||||
* If proto or parent are NULL, set them to Constructor.prototype and/or
|
||||
* Constructor.__parent__, just like JSOP_NEW does.
|
||||
* If proto is NULL, set it to Constructor.prototype, just like JSOP_NEW
|
||||
* does, likewise for the new object's parent.
|
||||
*/
|
||||
ctor = JSVAL_TO_OBJECT(cval);
|
||||
if (!parent)
|
||||
|
@ -3900,7 +3848,7 @@ js_AllocSlot(JSContext *cx, JSObject *obj, uint32 *slotp)
|
|||
}
|
||||
|
||||
if (scope->freeslot >= obj->numSlots() &&
|
||||
!js_GrowSlots(cx, obj, scope->freeslot + 1)) {
|
||||
!obj->growSlots(cx, scope->freeslot + 1)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
|
@ -5691,10 +5639,10 @@ js_CheckAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode,
|
|||
* We don't want to require all classes to supply a checkAccess hook; we
|
||||
* need that hook only for certain classes used when precompiling scripts
|
||||
* and functions ("brutal sharing"). But for general safety of built-in
|
||||
* magic properties such as __proto__ and __parent__, we route all access
|
||||
* checks, even for classes that stub out checkAccess, through the global
|
||||
* checkObjectAccess hook. This covers precompilation-based sharing and
|
||||
* (possibly unintended) runtime sharing across trust boundaries.
|
||||
* magic properties like __proto__, we route all access checks, even for
|
||||
* classes that stub out checkAccess, through the global checkObjectAccess
|
||||
* hook. This covers precompilation-based sharing and (possibly
|
||||
* unintended) runtime sharing across trust boundaries.
|
||||
*/
|
||||
clasp = pobj->getClass();
|
||||
check = clasp->checkAccess;
|
||||
|
@ -6304,7 +6252,7 @@ js_TraceObject(JSTracer *trc, JSObject *obj)
|
|||
*/
|
||||
size_t slots = scope->freeslot;
|
||||
if (obj->numSlots() != slots)
|
||||
js_ShrinkSlots(cx, obj, slots);
|
||||
obj->shrinkSlots(cx, slots);
|
||||
}
|
||||
|
||||
#ifdef JS_DUMP_SCOPE_METERS
|
||||
|
@ -6432,17 +6380,17 @@ js_SetReservedSlot(JSContext *cx, JSObject *obj, uint32 index, jsval v)
|
|||
#endif
|
||||
|
||||
uint32 slot = JSSLOT_START(clasp) + index;
|
||||
if (slot >= JS_INITIAL_NSLOTS && !obj->dslots) {
|
||||
if (slot >= obj->numSlots()) {
|
||||
/*
|
||||
* At this point, obj may or may not own scope, and we may or may not
|
||||
* need to allocate dslots. If scope is shared, scope->freeslot may not
|
||||
* need to allocate slots. If scope is shared, scope->freeslot may not
|
||||
* be accurate for obj (see comment below).
|
||||
*/
|
||||
uint32 nslots = JSSLOT_FREE(clasp);
|
||||
if (clasp->reserveSlots)
|
||||
nslots += clasp->reserveSlots(cx, obj);
|
||||
JS_ASSERT(slot < nslots);
|
||||
if (!js_AllocSlots(cx, obj, nslots)) {
|
||||
if (!obj->allocSlots(cx, nslots)) {
|
||||
JS_UNLOCK_OBJ(cx, obj);
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -296,6 +296,22 @@ struct JSObject {
|
|||
return dslots ? (uint32)dslots[-1] : (uint32)JS_INITIAL_NSLOTS;
|
||||
}
|
||||
|
||||
private:
|
||||
static size_t slotsToDynamicWords(size_t nslots) {
|
||||
JS_ASSERT(nslots > JS_INITIAL_NSLOTS);
|
||||
return nslots + 1 - JS_INITIAL_NSLOTS;
|
||||
}
|
||||
|
||||
static size_t dynamicWordsToSlots(size_t nwords) {
|
||||
JS_ASSERT(nwords > 1);
|
||||
return nwords - 1 + JS_INITIAL_NSLOTS;
|
||||
}
|
||||
|
||||
public:
|
||||
bool allocSlots(JSContext *cx, size_t nslots);
|
||||
bool growSlots(JSContext *cx, size_t nslots);
|
||||
void shrinkSlots(JSContext *cx, size_t nslots);
|
||||
|
||||
jsval& getSlotRef(uintN slot) {
|
||||
return (slot < JS_INITIAL_NSLOTS)
|
||||
? fslots[slot]
|
||||
|
@ -364,7 +380,7 @@ struct JSObject {
|
|||
|
||||
JSObject *parent = getParent();
|
||||
if (parent)
|
||||
JS_CALL_OBJECT_TRACER(trc, parent, "__parent__");
|
||||
JS_CALL_OBJECT_TRACER(trc, parent, "parent");
|
||||
}
|
||||
|
||||
JSObject *getGlobal();
|
||||
|
@ -417,8 +433,6 @@ struct JSObject {
|
|||
// The static assertion isn't inline because that doesn't work on Mac.)
|
||||
inline void staticAssertArrayLengthIsInPrivateSlot();
|
||||
|
||||
inline bool isDenseArrayMinLenCapOk() const;
|
||||
|
||||
inline uint32 uncheckedGetArrayLength() const;
|
||||
inline uint32 uncheckedGetDenseArrayCapacity() const;
|
||||
|
||||
|
@ -435,7 +449,10 @@ struct JSObject {
|
|||
inline uint32 getDenseArrayCapacity() const;
|
||||
inline void setDenseArrayCapacity(uint32 capacity); // XXX: bug 558263 will remove this
|
||||
|
||||
inline bool isDenseArrayMinLenCapOk(bool strictAboutLength = true) const;
|
||||
|
||||
inline jsval getDenseArrayElement(uint32 i) const;
|
||||
inline jsval *addressOfDenseArrayElement(uint32 i);
|
||||
inline void setDenseArrayElement(uint32 i, jsval v);
|
||||
|
||||
inline jsval *getDenseArrayElements() const; // returns pointer to the Array's elements array
|
||||
|
@ -872,15 +889,6 @@ js_AllocSlot(JSContext *cx, JSObject *obj, uint32 *slotp);
|
|||
extern void
|
||||
js_FreeSlot(JSContext *cx, JSObject *obj, uint32 slot);
|
||||
|
||||
extern bool
|
||||
js_AllocSlots(JSContext *cx, JSObject *obj, size_t nslots);
|
||||
|
||||
extern bool
|
||||
js_GrowSlots(JSContext *cx, JSObject *obj, size_t nslots);
|
||||
|
||||
extern void
|
||||
js_ShrinkSlots(JSContext *cx, JSObject *obj, size_t nslots);
|
||||
|
||||
/*
|
||||
* Ensure that the object has at least JSCLASS_RESERVED_SLOTS(clasp)+nreserved
|
||||
* slots. The function can be called only for native objects just created with
|
||||
|
|
|
@ -46,10 +46,7 @@
|
|||
#include "jsiter.h"
|
||||
#include "jsobj.h"
|
||||
#include "jsscope.h"
|
||||
|
||||
#ifdef INCLUDE_MOZILLA_DTRACE
|
||||
#include "jsdtracef.h"
|
||||
#endif
|
||||
|
||||
#include "jsscopeinlines.h"
|
||||
|
||||
|
@ -110,18 +107,26 @@ JSObject::setPrimitiveThis(jsval pthis)
|
|||
fslots[JSSLOT_PRIMITIVE_THIS] = pthis;
|
||||
}
|
||||
|
||||
inline void JSObject::staticAssertArrayLengthIsInPrivateSlot()
|
||||
inline void
|
||||
JSObject::staticAssertArrayLengthIsInPrivateSlot()
|
||||
{
|
||||
JS_STATIC_ASSERT(JSSLOT_ARRAY_LENGTH == JSSLOT_PRIVATE);
|
||||
}
|
||||
|
||||
inline bool JSObject::isDenseArrayMinLenCapOk() const
|
||||
inline bool
|
||||
JSObject::isDenseArrayMinLenCapOk(bool strictAboutLength) const
|
||||
{
|
||||
JS_ASSERT(isDenseArray());
|
||||
uint32 length = uncheckedGetArrayLength();
|
||||
uint32 capacity = uncheckedGetDenseArrayCapacity();
|
||||
uint32 minLenCap = uint32(fslots[JSSLOT_DENSE_ARRAY_MINLENCAP]);
|
||||
return minLenCap == JS_MIN(length, capacity);
|
||||
|
||||
// This function can be called while the LENGTH and MINLENCAP slots are
|
||||
// still set to JSVAL_VOID and there are no dslots (ie. the capacity is
|
||||
// zero). If 'strictAboutLength' is false we allow this.
|
||||
return minLenCap == JS_MIN(length, capacity) ||
|
||||
(!strictAboutLength && minLenCap == uint32(JSVAL_VOID) &&
|
||||
length == uint32(JSVAL_VOID) && capacity == 0);
|
||||
}
|
||||
|
||||
inline uint32
|
||||
|
@ -192,7 +197,7 @@ inline uint32
|
|||
JSObject::getDenseArrayCapacity() const
|
||||
{
|
||||
JS_ASSERT(isDenseArray());
|
||||
JS_ASSERT(isDenseArrayMinLenCapOk());
|
||||
JS_ASSERT(isDenseArrayMinLenCapOk(/* strictAboutLength = */false));
|
||||
return uncheckedGetDenseArrayCapacity();
|
||||
}
|
||||
|
||||
|
@ -214,6 +219,14 @@ JSObject::getDenseArrayElement(uint32 i) const
|
|||
return dslots[i];
|
||||
}
|
||||
|
||||
inline jsval *
|
||||
JSObject::addressOfDenseArrayElement(uint32 i)
|
||||
{
|
||||
JS_ASSERT(isDenseArray());
|
||||
JS_ASSERT(i < getDenseArrayCapacity());
|
||||
return &dslots[i];
|
||||
}
|
||||
|
||||
inline void
|
||||
JSObject::setDenseArrayElement(uint32 i, jsval v)
|
||||
{
|
||||
|
@ -477,7 +490,7 @@ InitScopeForObject(JSContext* cx, JSObject* obj, JSClass *clasp, JSObject* proto
|
|||
/* Let JSScope::create set freeslot so as to reserve slots. */
|
||||
JS_ASSERT(scope->freeslot >= JSSLOT_PRIVATE);
|
||||
if (scope->freeslot > JS_INITIAL_NSLOTS &&
|
||||
!js_AllocSlots(cx, obj, scope->freeslot)) {
|
||||
!obj->allocSlots(cx, scope->freeslot)) {
|
||||
scope->destroy(cx);
|
||||
goto bad;
|
||||
}
|
||||
|
@ -496,10 +509,7 @@ static inline JSObject *
|
|||
NewObjectWithGivenProto(JSContext *cx, JSClass *clasp, JSObject *proto,
|
||||
JSObject *parent, size_t objectSize = 0)
|
||||
{
|
||||
#ifdef INCLUDE_MOZILLA_DTRACE
|
||||
if (JAVASCRIPT_OBJECT_CREATE_START_ENABLED())
|
||||
jsdtrace_object_create_start(cx->fp, clasp);
|
||||
#endif
|
||||
DTrace::ObjectCreationScope objectCreationScope(cx, cx->fp, clasp);
|
||||
|
||||
/* Assert that the class is a proper class. */
|
||||
JS_ASSERT_IF(clasp->flags & JSCLASS_IS_EXTENDED,
|
||||
|
@ -565,12 +575,7 @@ NewObjectWithGivenProto(JSContext *cx, JSClass *clasp, JSObject *proto,
|
|||
}
|
||||
|
||||
out:
|
||||
#ifdef INCLUDE_MOZILLA_DTRACE
|
||||
if (JAVASCRIPT_OBJECT_CREATE_ENABLED())
|
||||
jsdtrace_object_create(cx, clasp, obj);
|
||||
if (JAVASCRIPT_OBJECT_CREATE_DONE_ENABLED())
|
||||
jsdtrace_object_create_done(cx->fp, clasp);
|
||||
#endif
|
||||
objectCreationScope.handleCreation(obj);
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
|
|
@ -3274,6 +3274,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
|
|||
cond -= tail;
|
||||
DECOMPILE_CODE(pc + oplen, cond - oplen);
|
||||
pc += cond;
|
||||
oplen = js_CodeSpec[*pc].length;
|
||||
elseif = JS_TRUE;
|
||||
goto if_again;
|
||||
}
|
||||
|
|
|
@ -3333,9 +3333,8 @@ BEGIN_CASE(JSOP_INITMETHOD)
|
|||
* So check first.
|
||||
*
|
||||
* On a hit, if the cached sprop has a non-default setter, it must be
|
||||
* __proto__ or __parent__. If sprop->parent != scope->lastProperty(),
|
||||
* there is a repeated property name. The fast path does not handle these
|
||||
* two cases.
|
||||
* __proto__. If sprop->parent != scope->lastProperty(), there is a
|
||||
* repeated property name. The fast path does not handle these two cases.
|
||||
*/
|
||||
if (CX_OWNS_OBJECT_TITLE(cx, obj) &&
|
||||
JS_PROPERTY_CACHE(cx).testForInit(rt, regs.pc, obj, scope, &sprop, &entry) &&
|
||||
|
|
|
@ -3198,7 +3198,7 @@ BindLet(JSContext *cx, BindData *data, JSAtom *atom, JSTreeContext *tc)
|
|||
*/
|
||||
uintN slot = JSSLOT_FREE(&js_BlockClass) + n;
|
||||
if (slot >= blockObj->numSlots() &&
|
||||
!js_GrowSlots(cx, blockObj, slot + 1)) {
|
||||
!blockObj->growSlots(cx, slot + 1)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
blockObj->scope()->freeslot = slot + 1;
|
||||
|
@ -6274,6 +6274,7 @@ Parser::unaryExpr()
|
|||
break;
|
||||
|
||||
case TOK_DELETE:
|
||||
{
|
||||
pn = UnaryNode::create(tc);
|
||||
if (!pn)
|
||||
return NULL;
|
||||
|
@ -6301,12 +6302,14 @@ Parser::unaryExpr()
|
|||
JSMSG_DEPRECATED_DELETE_OPERAND))
|
||||
return NULL;
|
||||
pn2->pn_op = JSOP_DELNAME;
|
||||
if (pn2->pn_atom == context->runtime->atomState.argumentsAtom)
|
||||
tc->flags |= TCF_FUN_HEAVYWEIGHT;
|
||||
break;
|
||||
default:;
|
||||
}
|
||||
pn->pn_kid = pn2;
|
||||
break;
|
||||
|
||||
}
|
||||
case TOK_ERROR:
|
||||
return NULL;
|
||||
|
||||
|
|
|
@ -55,7 +55,7 @@ class RecursiveSlotMap : public SlotMap
|
|||
{
|
||||
/* Check if the return value should be promoted. */
|
||||
if (slots[downPostSlots].lastCheck == TypeCheck_Demote)
|
||||
rval_ins = mRecorder.lir->ins1(LIR_i2f, rval_ins);
|
||||
rval_ins = mRecorder.lir->ins1(LIR_i2d, rval_ins);
|
||||
/* Adjust any global variables. */
|
||||
for (unsigned i = downPostSlots + 1; i < slots.length(); i++)
|
||||
adjustType(slots[i]);
|
||||
|
@ -111,10 +111,10 @@ class UpRecursiveSlotMap : public RecursiveSlotMap
|
|||
*/
|
||||
lir->insStore(rval_ins, lirbuf->sp, -mRecorder.tree->nativeStackBase, ACC_STACK);
|
||||
|
||||
lirbuf->sp = lir->ins2(LIR_piadd, lirbuf->sp,
|
||||
lirbuf->sp = lir->ins2(LIR_addp, lirbuf->sp,
|
||||
lir->insImmWord(-int(downPostSlots) * sizeof(double)));
|
||||
lir->insStore(lirbuf->sp, lirbuf->state, offsetof(TracerState, sp), ACC_OTHER);
|
||||
lirbuf->rp = lir->ins2(LIR_piadd, lirbuf->rp,
|
||||
lirbuf->rp = lir->ins2(LIR_addp, lirbuf->rp,
|
||||
lir->insImmWord(-int(sizeof(FrameInfo*))));
|
||||
lir->insStore(lirbuf->rp, lirbuf->state, offsetof(TracerState, rp), ACC_OTHER);
|
||||
}
|
||||
|
@ -286,8 +286,8 @@ TraceRecorder::upRecursion()
|
|||
|
||||
/* Guard that rp >= sr + 1 */
|
||||
guard(true,
|
||||
lir->ins2(LIR_pge, lirbuf->rp,
|
||||
lir->ins2(LIR_piadd,
|
||||
lir->ins2(LIR_gep, lirbuf->rp,
|
||||
lir->ins2(LIR_addp,
|
||||
lir->insLoad(LIR_ldp, lirbuf->state,
|
||||
offsetof(TracerState, sor), ACC_OTHER),
|
||||
INS_CONSTWORD(sizeof(FrameInfo*)))),
|
||||
|
@ -299,7 +299,7 @@ TraceRecorder::upRecursion()
|
|||
/* Guard that the FrameInfo above is the same FrameInfo pointer. */
|
||||
VMSideExit* exit = snapshot(RECURSIVE_MISMATCH_EXIT);
|
||||
LIns* prev_rp = lir->insLoad(LIR_ldp, lirbuf->rp, -int32_t(sizeof(FrameInfo*)), ACC_RSTACK);
|
||||
guard(true, lir->ins2(LIR_peq, prev_rp, INS_CONSTPTR(fi)), exit);
|
||||
guard(true, lir->ins2(LIR_eqp, prev_rp, INS_CONSTPTR(fi)), exit);
|
||||
|
||||
/*
|
||||
* Now it's time to try and close the loop. Get a special exit that points
|
||||
|
@ -419,7 +419,7 @@ TraceRecorder::slurpDownFrames(jsbytecode* return_pc)
|
|||
* end-of-recursion and recursion-returns-to-different-pc.
|
||||
*/
|
||||
guard(true,
|
||||
lir->ins2(LIR_peq,
|
||||
lir->ins2(LIR_eqp,
|
||||
addName(lir->insLoad(LIR_ldp, fp_ins,
|
||||
offsetof(JSStackFrame, script), ACC_OTHER),
|
||||
"script"),
|
||||
|
@ -429,7 +429,7 @@ TraceRecorder::slurpDownFrames(jsbytecode* return_pc)
|
|||
|
||||
/* fp->down->regs->pc should be == pc. */
|
||||
guard(true,
|
||||
lir->ins2(LIR_peq,
|
||||
lir->ins2(LIR_eqp,
|
||||
lir->insLoad(LIR_ldp,
|
||||
addName(lir->insLoad(LIR_ldp, fp_ins,
|
||||
offsetof(JSStackFrame, regs), ACC_OTHER),
|
||||
|
@ -440,8 +440,8 @@ TraceRecorder::slurpDownFrames(jsbytecode* return_pc)
|
|||
|
||||
/* fp->down->argc should be == argc. */
|
||||
guard(true,
|
||||
lir->ins2(LIR_eq,
|
||||
addName(lir->insLoad(LIR_ld, fp_ins, offsetof(JSStackFrame, argc),
|
||||
lir->ins2(LIR_eqi,
|
||||
addName(lir->insLoad(LIR_ldi, fp_ins, offsetof(JSStackFrame, argc),
|
||||
ACC_OTHER),
|
||||
"argc"),
|
||||
INS_CONST(cx->fp->argc)),
|
||||
|
@ -550,10 +550,10 @@ TraceRecorder::slurpDownFrames(jsbytecode* return_pc)
|
|||
case TT_SPECIAL:
|
||||
case TT_VOID:
|
||||
case TT_INT32:
|
||||
rval_ins = lir->insLoad(LIR_ld, lirbuf->sp, offset, ACC_STACK);
|
||||
rval_ins = lir->insLoad(LIR_ldi, lirbuf->sp, offset, ACC_STACK);
|
||||
break;
|
||||
case TT_DOUBLE:
|
||||
rval_ins = lir->insLoad(LIR_ldf, lirbuf->sp, offset, ACC_STACK);
|
||||
rval_ins = lir->insLoad(LIR_ldd, lirbuf->sp, offset, ACC_STACK);
|
||||
break;
|
||||
case TT_FUNCTION:
|
||||
case TT_OBJECT:
|
||||
|
@ -609,7 +609,7 @@ TraceRecorder::slurpDownFrames(jsbytecode* return_pc)
|
|||
/* stack vals */
|
||||
unsigned nfixed = fp->script->nfixed;
|
||||
jsval* stack = StackBase(fp);
|
||||
LIns* stack_ins = addName(lir->ins2(LIR_piadd,
|
||||
LIns* stack_ins = addName(lir->ins2(LIR_addp,
|
||||
slots_ins,
|
||||
INS_CONSTWORD(nfixed * sizeof(jsval))),
|
||||
"stackBase");
|
||||
|
@ -684,12 +684,12 @@ TraceRecorder::downRecursion()
|
|||
JS_ASSERT(tree->maxNativeStackSlots >= tree->nativeStackBase / sizeof(double));
|
||||
int guardSlots = slots + tree->maxNativeStackSlots -
|
||||
tree->nativeStackBase / sizeof(double);
|
||||
LIns* sp_top = lir->ins2(LIR_piadd, lirbuf->sp, lir->insImmWord(guardSlots * sizeof(double)));
|
||||
guard(true, lir->ins2(LIR_plt, sp_top, eos_ins), OOM_EXIT);
|
||||
LIns* sp_top = lir->ins2(LIR_addp, lirbuf->sp, lir->insImmWord(guardSlots * sizeof(double)));
|
||||
guard(true, lir->ins2(LIR_ltp, sp_top, eos_ins), OOM_EXIT);
|
||||
|
||||
/* Guard that there is enough call stack space. */
|
||||
LIns* rp_top = lir->ins2(LIR_piadd, lirbuf->rp, lir->insImmWord(sizeof(FrameInfo*)));
|
||||
guard(true, lir->ins2(LIR_plt, rp_top, eor_ins), OOM_EXIT);
|
||||
LIns* rp_top = lir->ins2(LIR_addp, lirbuf->rp, lir->insImmWord(sizeof(FrameInfo*)));
|
||||
guard(true, lir->ins2(LIR_ltp, rp_top, eor_ins), OOM_EXIT);
|
||||
|
||||
/*
|
||||
* For every slot in the new frame that is not in the tracker, create a load
|
||||
|
@ -702,9 +702,9 @@ TraceRecorder::downRecursion()
|
|||
VisitStackSlots(visitor, cx, callDepth);
|
||||
|
||||
/* Add space for a new JIT frame. */
|
||||
lirbuf->sp = lir->ins2(LIR_piadd, lirbuf->sp, lir->insImmWord(slots * sizeof(double)));
|
||||
lirbuf->sp = lir->ins2(LIR_addp, lirbuf->sp, lir->insImmWord(slots * sizeof(double)));
|
||||
lir->insStore(lirbuf->sp, lirbuf->state, offsetof(TracerState, sp), ACC_OTHER);
|
||||
lirbuf->rp = lir->ins2(LIR_piadd, lirbuf->rp, lir->insImmWord(sizeof(FrameInfo*)));
|
||||
lirbuf->rp = lir->ins2(LIR_addp, lirbuf->rp, lir->insImmWord(sizeof(FrameInfo*)));
|
||||
lir->insStore(lirbuf->rp, lirbuf->state, offsetof(TracerState, rp), ACC_OTHER);
|
||||
--callDepth;
|
||||
clearCurrentFrameSlotsFromTracker(nativeFrameTracker);
|
||||
|
@ -734,19 +734,19 @@ JS_REQUIRES_STACK LIns*
|
|||
TraceRecorder::slurpInt32Slot(LIns* val_ins, jsval* vp, VMSideExit* exit)
|
||||
{
|
||||
guard(true,
|
||||
lir->ins2(LIR_or,
|
||||
lir->ins2(LIR_peq,
|
||||
lir->ins2(LIR_piand, val_ins, INS_CONSTWORD(JSVAL_TAGMASK)),
|
||||
lir->ins2(LIR_ori,
|
||||
lir->ins2(LIR_eqp,
|
||||
lir->ins2(LIR_andp, val_ins, INS_CONSTWORD(JSVAL_TAGMASK)),
|
||||
INS_CONSTWORD(JSVAL_DOUBLE)),
|
||||
lir->ins2(LIR_peq,
|
||||
lir->ins2(LIR_piand, val_ins, INS_CONSTWORD(1)),
|
||||
lir->ins2(LIR_eqp,
|
||||
lir->ins2(LIR_andp, val_ins, INS_CONSTWORD(1)),
|
||||
INS_CONSTWORD(1))),
|
||||
exit);
|
||||
LIns* space = lir->insAlloc(sizeof(int32));
|
||||
LIns* args[] = { space, val_ins };
|
||||
LIns* result = lir->insCall(&js_TryUnboxInt32_ci, args);
|
||||
guard(false, lir->insEqI_0(result), exit);
|
||||
LIns* int32_ins = lir->insLoad(LIR_ld, space, 0, ACC_OTHER);
|
||||
LIns* int32_ins = lir->insLoad(LIR_ldi, space, 0, ACC_OTHER);
|
||||
return int32_ins;
|
||||
}
|
||||
|
||||
|
@ -754,12 +754,12 @@ JS_REQUIRES_STACK LIns*
|
|||
TraceRecorder::slurpDoubleSlot(LIns* val_ins, jsval* vp, VMSideExit* exit)
|
||||
{
|
||||
guard(true,
|
||||
lir->ins2(LIR_or,
|
||||
lir->ins2(LIR_peq,
|
||||
lir->ins2(LIR_piand, val_ins, INS_CONSTWORD(JSVAL_TAGMASK)),
|
||||
lir->ins2(LIR_ori,
|
||||
lir->ins2(LIR_eqp,
|
||||
lir->ins2(LIR_andp, val_ins, INS_CONSTWORD(JSVAL_TAGMASK)),
|
||||
INS_CONSTWORD(JSVAL_DOUBLE)),
|
||||
lir->ins2(LIR_peq,
|
||||
lir->ins2(LIR_piand, val_ins, INS_CONSTWORD(1)),
|
||||
lir->ins2(LIR_eqp,
|
||||
lir->ins2(LIR_andp, val_ins, INS_CONSTWORD(1)),
|
||||
INS_CONSTWORD(1))),
|
||||
exit);
|
||||
LIns* args[] = { val_ins };
|
||||
|
@ -771,11 +771,11 @@ JS_REQUIRES_STACK LIns*
|
|||
TraceRecorder::slurpSpecialSlot(LIns* val_ins, jsval* vp, VMSideExit* exit)
|
||||
{
|
||||
guard(true,
|
||||
lir->ins2(LIR_peq,
|
||||
lir->ins2(LIR_piand, val_ins, INS_CONSTWORD(JSVAL_TAGMASK)),
|
||||
lir->ins2(LIR_eqp,
|
||||
lir->ins2(LIR_andp, val_ins, INS_CONSTWORD(JSVAL_TAGMASK)),
|
||||
INS_CONSTWORD(JSVAL_SPECIAL)),
|
||||
exit);
|
||||
LIns* bool_ins = lir->ins2(LIR_pirsh, val_ins, INS_CONST(JSVAL_TAGBITS));
|
||||
LIns* bool_ins = lir->ins2(LIR_rshp, val_ins, INS_CONST(JSVAL_TAGBITS));
|
||||
bool_ins = p2i(bool_ins);
|
||||
return bool_ins;
|
||||
}
|
||||
|
@ -783,7 +783,7 @@ TraceRecorder::slurpSpecialSlot(LIns* val_ins, jsval* vp, VMSideExit* exit)
|
|||
JS_REQUIRES_STACK LIns*
|
||||
TraceRecorder::slurpVoidSlot(LIns* val_ins, jsval* vp, VMSideExit* exit)
|
||||
{
|
||||
guard(true, lir->ins2(LIR_peq, val_ins, INS_CONSTWORD(JSVAL_VOID)), exit);
|
||||
guard(true, lir->ins2(LIR_eqp, val_ins, INS_CONSTWORD(JSVAL_VOID)), exit);
|
||||
return INS_VOID();
|
||||
}
|
||||
|
||||
|
@ -791,11 +791,11 @@ JS_REQUIRES_STACK LIns*
|
|||
TraceRecorder::slurpStringSlot(LIns* val_ins, jsval* vp, VMSideExit* exit)
|
||||
{
|
||||
guard(true,
|
||||
lir->ins2(LIR_peq,
|
||||
lir->ins2(LIR_piand, val_ins, INS_CONSTWORD(JSVAL_TAGMASK)),
|
||||
lir->ins2(LIR_eqp,
|
||||
lir->ins2(LIR_andp, val_ins, INS_CONSTWORD(JSVAL_TAGMASK)),
|
||||
INS_CONSTWORD(JSVAL_STRING)),
|
||||
exit);
|
||||
LIns* str_ins = lir->ins2(LIR_piand, val_ins, INS_CONSTWORD(~JSVAL_TAGMASK));
|
||||
LIns* str_ins = lir->ins2(LIR_andp, val_ins, INS_CONSTWORD(~JSVAL_TAGMASK));
|
||||
return str_ins;
|
||||
}
|
||||
|
||||
|
@ -814,13 +814,13 @@ TraceRecorder::slurpObjectSlot(LIns* val_ins, jsval* vp, VMSideExit* exit)
|
|||
|
||||
/* Must be an object */
|
||||
guard(true,
|
||||
lir->insEqP_0(lir->ins2(LIR_piand, val_ins, INS_CONSTWORD(JSVAL_TAGMASK))),
|
||||
lir->insEqP_0(lir->ins2(LIR_andp, val_ins, INS_CONSTWORD(JSVAL_TAGMASK))),
|
||||
exit);
|
||||
|
||||
/* Must NOT have a function class */
|
||||
guard(false,
|
||||
lir->ins2(LIR_peq,
|
||||
lir->ins2(LIR_piand,
|
||||
lir->ins2(LIR_eqp,
|
||||
lir->ins2(LIR_andp,
|
||||
lir->insLoad(LIR_ldp, val_ins, offsetof(JSObject, classword),
|
||||
ACC_OTHER),
|
||||
INS_CONSTWORD(~JSSLOT_CLASS_MASK_BITS)),
|
||||
|
@ -837,13 +837,13 @@ TraceRecorder::slurpFunctionSlot(LIns* val_ins, jsval* vp, VMSideExit* exit)
|
|||
|
||||
/* Must be an object */
|
||||
guard(true,
|
||||
lir->insEqP_0(lir->ins2(LIR_piand, val_ins, INS_CONSTWORD(JSVAL_TAGMASK))),
|
||||
lir->insEqP_0(lir->ins2(LIR_andp, val_ins, INS_CONSTWORD(JSVAL_TAGMASK))),
|
||||
exit);
|
||||
|
||||
/* Must have a function class */
|
||||
guard(true,
|
||||
lir->ins2(LIR_peq,
|
||||
lir->ins2(LIR_piand,
|
||||
lir->ins2(LIR_eqp,
|
||||
lir->ins2(LIR_andp,
|
||||
lir->insLoad(LIR_ldp, val_ins, offsetof(JSObject, classword),
|
||||
ACC_OTHER),
|
||||
INS_CONSTWORD(~JSSLOT_CLASS_MASK_BITS)),
|
||||
|
|
|
@ -2382,10 +2382,10 @@ class RegExpNativeCompiler {
|
|||
|
||||
LIns* compileFlatSingleChar(jschar ch, LIns* pos, LInsList& fails)
|
||||
{
|
||||
LIns* to_fail = lir->insBranch(LIR_jf, lir->ins2(LIR_plt, pos, cpend), 0);
|
||||
LIns* to_fail = lir->insBranch(LIR_jf, lir->ins2(LIR_ltp, pos, cpend), 0);
|
||||
if (!fails.append(to_fail))
|
||||
return NULL;
|
||||
LIns* text_ch = lir->insLoad(LIR_ldzs, pos, 0, ACC_READONLY);
|
||||
LIns* text_ch = lir->insLoad(LIR_ldus2ui, pos, 0, ACC_READONLY);
|
||||
|
||||
// Extra characters that need to be compared against when doing folding.
|
||||
struct extra {
|
||||
|
@ -2402,7 +2402,7 @@ class RegExpNativeCompiler {
|
|||
if (ch != lch) {
|
||||
if (L'A' <= ch && ch <= L'Z') {
|
||||
// Fast conversion of text character to lower case by OR-ing with 32.
|
||||
text_ch = lir->ins2(LIR_or, text_ch, lir->insImmI(32));
|
||||
text_ch = lir->ins2(LIR_ori, text_ch, lir->insImmI(32));
|
||||
// These ASCII letters have 2 lower-case forms. We put the ASCII one in
|
||||
// |extras| so it is tested first, because we expect that to be the common
|
||||
// case. Note that the code points of the non-ASCII forms both have the
|
||||
|
@ -2464,17 +2464,17 @@ class RegExpNativeCompiler {
|
|||
|
||||
gen:
|
||||
for (int i = 0; i < nextras; ++i) {
|
||||
LIns *test = lir->ins2(LIR_eq, text_ch, lir->insImmI(extras[i].ch));
|
||||
LIns *test = lir->ins2(LIR_eqi, text_ch, lir->insImmI(extras[i].ch));
|
||||
LIns *branch = lir->insBranch(LIR_jt, test, 0);
|
||||
extras[i].match = branch;
|
||||
}
|
||||
|
||||
if (!fails.append(lir->insBranch(LIR_jf, lir->ins2(LIR_eq, text_ch, lir->insImmI(ch)), 0)))
|
||||
if (!fails.append(lir->insBranch(LIR_jf, lir->ins2(LIR_eqi, text_ch, lir->insImmI(ch)), 0)))
|
||||
return NULL;
|
||||
|
||||
for (int i = 0; i < nextras; ++i)
|
||||
targetCurrentPoint(extras[i].match);
|
||||
return lir->ins2(LIR_piadd, pos, lir->insImmWord(2));
|
||||
return lir->ins2(LIR_addp, pos, lir->insImmWord(2));
|
||||
}
|
||||
|
||||
JS_INLINE bool hasCases(jschar ch)
|
||||
|
@ -2516,22 +2516,22 @@ class RegExpNativeCompiler {
|
|||
}
|
||||
|
||||
LIns* to_fail = lir->insBranch(LIR_jf,
|
||||
lir->ins2(LIR_plt,
|
||||
lir->ins2(LIR_ltp,
|
||||
pos,
|
||||
lir->ins2(LIR_piadd,
|
||||
lir->ins2(LIR_addp,
|
||||
cpend,
|
||||
lir->insImmWord(-2))),
|
||||
0);
|
||||
if (!fails.append(to_fail))
|
||||
return NULL;
|
||||
LIns* text_word = lir->insLoad(LIR_ld, pos, 0, ACC_OTHER);
|
||||
LIns* text_word = lir->insLoad(LIR_ldi, pos, 0, ACC_OTHER);
|
||||
LIns* comp_word = useFastCI ?
|
||||
lir->ins2(LIR_or, text_word, lir->insImmI(mask.i)) :
|
||||
lir->ins2(LIR_ori, text_word, lir->insImmI(mask.i)) :
|
||||
text_word;
|
||||
if (!fails.append(lir->insBranch(LIR_jf, lir->ins2(LIR_eq, comp_word, lir->insImmI(word)), 0)))
|
||||
if (!fails.append(lir->insBranch(LIR_jf, lir->ins2(LIR_eqi, comp_word, lir->insImmI(word)), 0)))
|
||||
return NULL;
|
||||
|
||||
return lir->ins2(LIR_piadd, pos, lir->insImmWord(4));
|
||||
return lir->ins2(LIR_addp, pos, lir->insImmWord(4));
|
||||
}
|
||||
|
||||
LIns* compileFlat(RENode *&node, LIns* pos, LInsList& fails)
|
||||
|
@ -2603,27 +2603,27 @@ class RegExpNativeCompiler {
|
|||
return NULL;
|
||||
memcpy(bitmapData, charSet->u.bits, bitmapLen);
|
||||
|
||||
LIns* to_fail = lir->insBranch(LIR_jf, lir->ins2(LIR_plt, pos, cpend), 0);
|
||||
LIns* to_fail = lir->insBranch(LIR_jf, lir->ins2(LIR_ltp, pos, cpend), 0);
|
||||
if (!fails.append(to_fail))
|
||||
return NULL;
|
||||
LIns* text_ch = lir->insLoad(LIR_ldzs, pos, 0, ACC_READONLY);
|
||||
LIns* text_ch = lir->insLoad(LIR_ldus2ui, pos, 0, ACC_READONLY);
|
||||
if (!fails.append(lir->insBranch(LIR_jf,
|
||||
lir->ins2(LIR_le, text_ch, lir->insImmI(charSet->length)),
|
||||
lir->ins2(LIR_lei, text_ch, lir->insImmI(charSet->length)),
|
||||
0))) {
|
||||
return NULL;
|
||||
}
|
||||
LIns* byteIndex = lir->insI2P(lir->ins2(LIR_rsh, text_ch, lir->insImmI(3)));
|
||||
LIns* byteIndex = lir->insI2P(lir->ins2(LIR_rshi, text_ch, lir->insImmI(3)));
|
||||
LIns* bitmap = lir->insImmP(bitmapData);
|
||||
LIns* byte = lir->insLoad(LIR_ldzb, lir->ins2(LIR_piadd, bitmap, byteIndex), (int) 0,
|
||||
LIns* byte = lir->insLoad(LIR_lduc2ui, lir->ins2(LIR_addp, bitmap, byteIndex), (int) 0,
|
||||
ACC_READONLY);
|
||||
LIns* bitMask = lir->ins2(LIR_lsh, lir->insImmI(1),
|
||||
lir->ins2(LIR_and, text_ch, lir->insImmI(0x7)));
|
||||
LIns* test = lir->ins2(LIR_eq, lir->ins2(LIR_and, byte, bitMask), lir->insImmI(0));
|
||||
LIns* bitMask = lir->ins2(LIR_lshi, lir->insImmI(1),
|
||||
lir->ins2(LIR_andi, text_ch, lir->insImmI(0x7)));
|
||||
LIns* test = lir->ins2(LIR_eqi, lir->ins2(LIR_andi, byte, bitMask), lir->insImmI(0));
|
||||
|
||||
LIns* to_next = lir->insBranch(LIR_jt, test, 0);
|
||||
if (!fails.append(to_next))
|
||||
return NULL;
|
||||
return lir->ins2(LIR_piadd, pos, lir->insImmWord(2));
|
||||
return lir->ins2(LIR_addp, pos, lir->insImmWord(2));
|
||||
}
|
||||
|
||||
/* Factor out common code to index js_alnum. */
|
||||
|
@ -2631,44 +2631,44 @@ class RegExpNativeCompiler {
|
|||
{
|
||||
if (sizeof(bool) != 1) {
|
||||
LIns *sizeLog2 = lir->insImmI(StaticLog2<sizeof(bool)>::result);
|
||||
chr = lir->ins2(LIR_lsh, chr, sizeLog2);
|
||||
chr = lir->ins2(LIR_lshi, chr, sizeLog2);
|
||||
}
|
||||
LIns *addr = lir->ins2(LIR_piadd, lir->insImmP(tbl), lir->insUI2P(chr));
|
||||
return lir->insLoad(LIR_ldzb, addr, 0, ACC_READONLY);
|
||||
LIns *addr = lir->ins2(LIR_addp, lir->insImmP(tbl), lir->insUI2P(chr));
|
||||
return lir->insLoad(LIR_lduc2ui, addr, 0, ACC_READONLY);
|
||||
}
|
||||
|
||||
/* Compile a builtin character class. */
|
||||
LIns *compileBuiltinClass(RENode *node, LIns *pos, LInsList &fails)
|
||||
{
|
||||
/* All the builtins checked below consume one character. */
|
||||
if (!fails.append(lir->insBranch(LIR_jf, lir->ins2(LIR_plt, pos, cpend), 0)))
|
||||
if (!fails.append(lir->insBranch(LIR_jf, lir->ins2(LIR_ltp, pos, cpend), 0)))
|
||||
return NULL;
|
||||
LIns *chr = lir->insLoad(LIR_ldzs, pos, 0, ACC_READONLY);
|
||||
LIns *chr = lir->insLoad(LIR_ldus2ui, pos, 0, ACC_READONLY);
|
||||
|
||||
switch (node->op) {
|
||||
case REOP_DOT:
|
||||
{
|
||||
/* Accept any character except those in ECMA-262 15.10.2.8. */
|
||||
LIns *eq1 = lir->ins2(LIR_eq, chr, lir->insImmI('\n'));
|
||||
LIns *eq1 = lir->ins2(LIR_eqi, chr, lir->insImmI('\n'));
|
||||
if (!fails.append(lir->insBranch(LIR_jt, eq1, NULL)))
|
||||
return NULL;
|
||||
LIns *eq2 = lir->ins2(LIR_eq, chr, lir->insImmI('\r'));
|
||||
LIns *eq2 = lir->ins2(LIR_eqi, chr, lir->insImmI('\r'));
|
||||
if (!fails.append(lir->insBranch(LIR_jt, eq2, NULL)))
|
||||
return NULL;
|
||||
LIns *eq3 = lir->ins2(LIR_eq, chr, lir->insImmI(LINE_SEPARATOR));
|
||||
LIns *eq3 = lir->ins2(LIR_eqi, chr, lir->insImmI(LINE_SEPARATOR));
|
||||
if (!fails.append(lir->insBranch(LIR_jt, eq3, NULL)))
|
||||
return NULL;
|
||||
LIns *eq4 = lir->ins2(LIR_eq, chr, lir->insImmI(PARA_SEPARATOR));
|
||||
LIns *eq4 = lir->ins2(LIR_eqi, chr, lir->insImmI(PARA_SEPARATOR));
|
||||
if (!fails.append(lir->insBranch(LIR_jt, eq4, NULL)))
|
||||
return NULL;
|
||||
break;
|
||||
}
|
||||
case REOP_DIGIT:
|
||||
{
|
||||
LIns *ge = lir->ins2(LIR_ge, chr, lir->insImmI('0'));
|
||||
LIns *ge = lir->ins2(LIR_gei, chr, lir->insImmI('0'));
|
||||
if (!fails.append(lir->insBranch(LIR_jf, ge, NULL)))
|
||||
return NULL;
|
||||
LIns *le = lir->ins2(LIR_le, chr, lir->insImmI('9'));
|
||||
LIns *le = lir->ins2(LIR_lei, chr, lir->insImmI('9'));
|
||||
if (!fails.append(lir->insBranch(LIR_jf, le, NULL)))
|
||||
return NULL;
|
||||
break;
|
||||
|
@ -2676,9 +2676,9 @@ class RegExpNativeCompiler {
|
|||
case REOP_NONDIGIT:
|
||||
{
|
||||
/* Use 'and' to give a predictable branch for success path. */
|
||||
LIns *ge = lir->ins2(LIR_ge, chr, lir->insImmI('0'));
|
||||
LIns *le = lir->ins2(LIR_le, chr, lir->insImmI('9'));
|
||||
LIns *both = lir->ins2(LIR_and, ge, le);
|
||||
LIns *ge = lir->ins2(LIR_gei, chr, lir->insImmI('0'));
|
||||
LIns *le = lir->ins2(LIR_lei, chr, lir->insImmI('9'));
|
||||
LIns *both = lir->ins2(LIR_andi, ge, le);
|
||||
if (!fails.append(lir->insBranch(LIR_jf, lir->insEqI_0(both), NULL)))
|
||||
return NULL;
|
||||
break;
|
||||
|
@ -2689,7 +2689,7 @@ class RegExpNativeCompiler {
|
|||
* Compile the condition:
|
||||
* ((uint)*cp) < 128 && js_alnum[(uint)*cp]
|
||||
*/
|
||||
LIns *rangeCnd = lir->ins2(LIR_ult, chr, lir->insImmI(128));
|
||||
LIns *rangeCnd = lir->ins2(LIR_ltui, chr, lir->insImmI(128));
|
||||
if (!fails.append(lir->insBranch(LIR_jf, rangeCnd, NULL)))
|
||||
return NULL;
|
||||
LIns *tableVal = compileTableRead(chr, js_alnum);
|
||||
|
@ -2703,7 +2703,7 @@ class RegExpNativeCompiler {
|
|||
* Compile the condition:
|
||||
* ((uint)*cp) >= 128 || !js_alnum[(uint)*cp]
|
||||
*/
|
||||
LIns *rangeCnd = lir->ins2(LIR_uge, chr, lir->insImmI(128));
|
||||
LIns *rangeCnd = lir->ins2(LIR_geui, chr, lir->insImmI(128));
|
||||
LIns *rangeBr = lir->insBranch(LIR_jt, rangeCnd, NULL);
|
||||
LIns *tableVal = compileTableRead(chr, js_alnum);
|
||||
if (!fails.append(lir->insBranch(LIR_jf, lir->insEqI_0(tableVal), NULL)))
|
||||
|
@ -2729,45 +2729,45 @@ class RegExpNativeCompiler {
|
|||
* (200A, max): 2028, 2029, 202F, 205F, 3000
|
||||
*/
|
||||
/* Below 0x20? */
|
||||
LIns *tableRangeCnd = lir->ins2(LIR_ule, chr, lir->insImmI(0x20));
|
||||
LIns *tableRangeCnd = lir->ins2(LIR_leui, chr, lir->insImmI(0x20));
|
||||
LIns *tableRangeBr = lir->insBranch(LIR_jt, tableRangeCnd, NULL);
|
||||
/* Fall through means *chr > 0x20. */
|
||||
|
||||
/* Handle (0x20,0xA0). */
|
||||
LIns *asciiCnd = lir->ins2(LIR_ult, chr, lir->insImmI(0xA0));
|
||||
LIns *asciiCnd = lir->ins2(LIR_ltui, chr, lir->insImmI(0xA0));
|
||||
LIns *asciiMissBr = lir->insBranch(LIR_jt, asciiCnd, NULL);
|
||||
/* Fall through means *chr >= 0xA0. */
|
||||
|
||||
/* Partition around [0x2000,0x200A]. */
|
||||
LIns *belowCnd = lir->ins2(LIR_ult, chr, lir->insImmI(0x2000));
|
||||
LIns *belowCnd = lir->ins2(LIR_ltui, chr, lir->insImmI(0x2000));
|
||||
LIns *belowBr = lir->insBranch(LIR_jt, belowCnd, NULL);
|
||||
LIns *aboveCnd = lir->ins2(LIR_ugt, chr, lir->insImmI(0x200A));
|
||||
LIns *aboveCnd = lir->ins2(LIR_gtui, chr, lir->insImmI(0x200A));
|
||||
LIns *aboveBr = lir->insBranch(LIR_jt, aboveCnd, NULL);
|
||||
LIns *intervalMatchBr = lir->insBranch(LIR_j, NULL, NULL);
|
||||
|
||||
/* Handle [0xA0,0x2000). */
|
||||
LIns *belowLbl = lir->ins0(LIR_label);
|
||||
belowBr->setTarget(belowLbl);
|
||||
LIns *eq1Cnd = lir->ins2(LIR_eq, chr, lir->insImmI(0xA0));
|
||||
LIns *eq1Cnd = lir->ins2(LIR_eqi, chr, lir->insImmI(0xA0));
|
||||
LIns *eq1Br = lir->insBranch(LIR_jt, eq1Cnd, NULL);
|
||||
LIns *eq2Cnd = lir->ins2(LIR_eq, chr, lir->insImmI(0x1680));
|
||||
LIns *eq2Cnd = lir->ins2(LIR_eqi, chr, lir->insImmI(0x1680));
|
||||
LIns *eq2Br = lir->insBranch(LIR_jt, eq2Cnd, NULL);
|
||||
LIns *eq3Cnd = lir->ins2(LIR_eq, chr, lir->insImmI(0x180E));
|
||||
LIns *eq3Cnd = lir->ins2(LIR_eqi, chr, lir->insImmI(0x180E));
|
||||
LIns *eq3Br = lir->insBranch(LIR_jt, eq3Cnd, NULL);
|
||||
LIns *belowMissBr = lir->insBranch(LIR_j, NULL, NULL);
|
||||
|
||||
/* Handle (0x200A, max). */
|
||||
LIns *aboveLbl = lir->ins0(LIR_label);
|
||||
aboveBr->setTarget(aboveLbl);
|
||||
LIns *eq4Cnd = lir->ins2(LIR_eq, chr, lir->insImmI(0x2028));
|
||||
LIns *eq4Cnd = lir->ins2(LIR_eqi, chr, lir->insImmI(0x2028));
|
||||
LIns *eq4Br = lir->insBranch(LIR_jt, eq4Cnd, NULL);
|
||||
LIns *eq5Cnd = lir->ins2(LIR_eq, chr, lir->insImmI(0x2029));
|
||||
LIns *eq5Cnd = lir->ins2(LIR_eqi, chr, lir->insImmI(0x2029));
|
||||
LIns *eq5Br = lir->insBranch(LIR_jt, eq5Cnd, NULL);
|
||||
LIns *eq6Cnd = lir->ins2(LIR_eq, chr, lir->insImmI(0x202F));
|
||||
LIns *eq6Cnd = lir->ins2(LIR_eqi, chr, lir->insImmI(0x202F));
|
||||
LIns *eq6Br = lir->insBranch(LIR_jt, eq6Cnd, NULL);
|
||||
LIns *eq7Cnd = lir->ins2(LIR_eq, chr, lir->insImmI(0x205F));
|
||||
LIns *eq7Cnd = lir->ins2(LIR_eqi, chr, lir->insImmI(0x205F));
|
||||
LIns *eq7Br = lir->insBranch(LIR_jt, eq7Cnd, NULL);
|
||||
LIns *eq8Cnd = lir->ins2(LIR_eq, chr, lir->insImmI(0x3000));
|
||||
LIns *eq8Cnd = lir->ins2(LIR_eqi, chr, lir->insImmI(0x3000));
|
||||
LIns *eq8Br = lir->insBranch(LIR_jt, eq8Cnd, NULL);
|
||||
LIns *aboveMissBr = lir->insBranch(LIR_j, NULL, NULL);
|
||||
|
||||
|
@ -2814,7 +2814,7 @@ class RegExpNativeCompiler {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
return lir->ins2(LIR_piadd, pos, lir->insImmWord(2));
|
||||
return lir->ins2(LIR_addp, pos, lir->insImmWord(2));
|
||||
}
|
||||
|
||||
LIns *compileAlt(RENode *node, LIns *pos, bool atEnd, LInsList &fails)
|
||||
|
@ -2977,7 +2977,7 @@ class RegExpNativeCompiler {
|
|||
* we need to abort the loop or else we will loop forever.
|
||||
*/
|
||||
if (mayMatchEmpty(bodyRe)) {
|
||||
LIns *eqCnd = lir->ins2(LIR_peq, iterBegin, iterEnd);
|
||||
LIns *eqCnd = lir->ins2(LIR_eqp, iterBegin, iterEnd);
|
||||
if (!kidFails.append(lir->insBranch(LIR_jt, eqCnd, NULL)))
|
||||
return NULL;
|
||||
}
|
||||
|
@ -3012,9 +3012,9 @@ class RegExpNativeCompiler {
|
|||
* conditionally executed, and we (currently) don't have real phi
|
||||
* nodes, we need only consider insns defined in A and used in E.
|
||||
*/
|
||||
lir->ins1(LIR_plive, state);
|
||||
lir->ins1(LIR_plive, cpend);
|
||||
lir->ins1(LIR_plive, start);
|
||||
lir->ins1(LIR_livep, state);
|
||||
lir->ins1(LIR_livep, cpend);
|
||||
lir->ins1(LIR_livep, start);
|
||||
|
||||
/* After the loop: reload 'pos' from memory and continue. */
|
||||
targetCurrentPoint(kidFails);
|
||||
|
@ -3083,13 +3083,13 @@ class RegExpNativeCompiler {
|
|||
/* Fall-through from compileNode means success. */
|
||||
lir->insStore(pos, state, offsetof(REGlobalData, stateStack), ACC_OTHER);
|
||||
lir->ins0(LIR_regfence);
|
||||
lir->ins1(LIR_ret, lir->insImmI(1));
|
||||
lir->ins1(LIR_reti, lir->insImmI(1));
|
||||
|
||||
/* Stick return here so we don't have to jump over it every time. */
|
||||
if (anchorFail) {
|
||||
targetCurrentPoint(anchorFail);
|
||||
lir->ins0(LIR_regfence);
|
||||
lir->ins1(LIR_ret, lir->insImmI(0));
|
||||
lir->ins1(LIR_reti, lir->insImmI(0));
|
||||
}
|
||||
|
||||
/* Target failed matches. */
|
||||
|
@ -3105,7 +3105,7 @@ class RegExpNativeCompiler {
|
|||
|
||||
/* Failed to match on first character, so fail whole match. */
|
||||
lir->ins0(LIR_regfence);
|
||||
lir->ins1(LIR_ret, lir->insImmI(0));
|
||||
lir->ins1(LIR_reti, lir->insImmI(0));
|
||||
return !outOfMemory();
|
||||
}
|
||||
|
||||
|
@ -3113,13 +3113,13 @@ class RegExpNativeCompiler {
|
|||
bool compileAnchoring(RENode *root, LIns *start)
|
||||
{
|
||||
/* Guard outer anchoring loop. Use <= to allow empty regexp match. */
|
||||
LIns *anchorFail = lir->insBranch(LIR_jf, lir->ins2(LIR_ple, start, cpend), 0);
|
||||
LIns *anchorFail = lir->insBranch(LIR_jf, lir->ins2(LIR_lep, start, cpend), 0);
|
||||
|
||||
if (!compileRootNode(root, start, anchorFail))
|
||||
return false;
|
||||
|
||||
/* Outer loop increment. */
|
||||
lir->insStore(lir->ins2(LIR_piadd, start, lir->insImmWord(2)), state,
|
||||
lir->insStore(lir->ins2(LIR_addp, start, lir->insImmWord(2)), state,
|
||||
offsetof(REGlobalData, skipped), ACC_OTHER);
|
||||
|
||||
return !outOfMemory();
|
||||
|
@ -3144,8 +3144,8 @@ class RegExpNativeCompiler {
|
|||
if (loopLabel) {
|
||||
lir->insBranch(LIR_j, NULL, loopLabel);
|
||||
LirBuffer* lirbuf = fragment->lirbuf;
|
||||
lir->ins1(LIR_plive, lirbuf->state);
|
||||
lir->ins1(LIR_plive, lirbuf->param1);
|
||||
lir->ins1(LIR_livep, lirbuf->state);
|
||||
lir->ins1(LIR_livep, lirbuf->param1);
|
||||
}
|
||||
|
||||
Allocator &alloc = *JS_TRACE_MONITOR(cx).dataAlloc;
|
||||
|
|
|
@ -8275,7 +8275,7 @@ TraceRecorder::i2d(LIns* i)
|
|||
}
|
||||
|
||||
LIns*
|
||||
TraceRecorder::d2i(LIns* f)
|
||||
TraceRecorder::d2i(LIns* f, bool resultCanBeImpreciseIfFractional)
|
||||
{
|
||||
if (f->isImmD())
|
||||
return lir->insImmI(js_DoubleToECMAInt32(f->immD()));
|
||||
|
@ -8314,7 +8314,9 @@ TraceRecorder::d2i(LIns* f)
|
|||
return lir->insCall(&js_String_p_charCodeAt_double_int_ci, args);
|
||||
}
|
||||
}
|
||||
return lir->insCall(&js_DoubleToInt32_ci, &f);
|
||||
return resultCanBeImpreciseIfFractional
|
||||
? lir->ins1(LIR_d2i, f)
|
||||
: lir->insCall(&js_DoubleToInt32_ci, &f);
|
||||
}
|
||||
|
||||
LIns*
|
||||
|
@ -8333,7 +8335,10 @@ TraceRecorder::makeNumberInt32(LIns* f)
|
|||
JS_ASSERT(f->isD());
|
||||
LIns* x;
|
||||
if (!isPromote(f)) {
|
||||
x = d2i(f);
|
||||
// This means "convert double to int if it's integral, otherwise
|
||||
// exit". We first convert the double to an int, then convert it back
|
||||
// and exit if the two doubles don't match.
|
||||
x = d2i(f, /* resultCanBeImpreciseIfFractional = */true);
|
||||
guard(true, lir->ins2(LIR_feq, f, lir->ins1(LIR_i2f, x)), MISMATCH_EXIT);
|
||||
} else {
|
||||
x = demote(lir, f);
|
||||
|
@ -13146,6 +13151,7 @@ TraceRecorder::denseArrayElement(jsval& oval, jsval& ival, jsval*& vp, LIns*& v_
|
|||
}
|
||||
|
||||
/* If not idx < min(length, capacity), stay on trace (and read value as undefined). */
|
||||
JS_ASSERT(obj->isDenseArrayMinLenCapOk());
|
||||
LIns* minLenCap =
|
||||
addName(stobj_get_fslot(obj_ins, JSObject::JSSLOT_DENSE_ARRAY_MINLENCAP), "minLenCap");
|
||||
LIns* br2 = lir->insBranch(LIR_jf,
|
||||
|
@ -13176,6 +13182,7 @@ TraceRecorder::denseArrayElement(jsval& oval, jsval& ival, jsval*& vp, LIns*& v_
|
|||
}
|
||||
|
||||
/* Guard array min(length, capacity). */
|
||||
JS_ASSERT(obj->isDenseArrayMinLenCapOk());
|
||||
LIns* minLenCap =
|
||||
addName(stobj_get_fslot(obj_ins, JSObject::JSSLOT_DENSE_ARRAY_MINLENCAP), "minLenCap");
|
||||
guard(true,
|
||||
|
|
|
@ -1186,7 +1186,7 @@ class TraceRecorder
|
|||
nanojit::LIns* s0, nanojit::LIns* s1);
|
||||
|
||||
nanojit::LIns* i2d(nanojit::LIns* i);
|
||||
nanojit::LIns* d2i(nanojit::LIns* f);
|
||||
nanojit::LIns* d2i(nanojit::LIns* f, bool resultCanBeImpreciseIfFractional = false);
|
||||
nanojit::LIns* f2u(nanojit::LIns* f);
|
||||
JS_REQUIRES_STACK nanojit::LIns* makeNumberInt32(nanojit::LIns* f);
|
||||
JS_REQUIRES_STACK nanojit::LIns* stringify(jsval& v);
|
||||
|
|
|
@ -407,6 +407,11 @@ def PRMJ_Now():
|
|||
|
||||
*/
|
||||
|
||||
// We parameterize the delay count just so that shell builds can
|
||||
// set it to 0 in order to get high-resolution benchmarking.
|
||||
// 10 seems to be the number of calls to load with a blank homepage.
|
||||
int CALIBRATION_DELAY_COUNT = 10;
|
||||
|
||||
JSInt64
|
||||
PRMJ_Now(void)
|
||||
{
|
||||
|
@ -424,8 +429,7 @@ PRMJ_Now(void)
|
|||
This does not appear to be needed on Vista as the timeBegin/timeEndPeriod
|
||||
calls seem to immediately take effect. */
|
||||
int thiscall = JS_ATOMIC_INCREMENT(&nCalls);
|
||||
/* 10 seems to be the number of calls to load with a blank homepage */
|
||||
if (thiscall <= 10) {
|
||||
if (thiscall <= CALIBRATION_DELAY_COUNT) {
|
||||
LowResTime(&ft);
|
||||
return (FILETIME2INT64(ft)-win2un)/10L;
|
||||
}
|
||||
|
|
|
@ -3658,6 +3658,34 @@ Elapsed(JSContext *cx, uintN argc, jsval *vp)
|
|||
return JS_FALSE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
Parent(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
if (argc != 1) {
|
||||
JS_ReportError(cx, "Wrong number of arguments");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
jsval v = JS_ARGV(cx, vp)[0];
|
||||
if (JSVAL_IS_PRIMITIVE(v)) {
|
||||
JS_ReportError(cx, "Only objects have parents!");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
JSObject *parent = JS_GetParent(cx, JSVAL_TO_OBJECT(v));
|
||||
*vp = OBJECT_TO_JSVAL(parent);
|
||||
|
||||
/* Outerize if necessary. Embrace the ugliness! */
|
||||
JSClass *clasp = JS_GET_CLASS(cx, parent);
|
||||
if (clasp->flags & JSCLASS_IS_EXTENDED) {
|
||||
JSExtendedClass *xclasp = reinterpret_cast<JSExtendedClass *>(clasp);
|
||||
if (JSObjectOp outerize = xclasp->outerObject)
|
||||
*vp = OBJECT_TO_JSVAL(outerize(cx, parent));
|
||||
}
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
#ifdef XP_UNIX
|
||||
|
||||
#include <fcntl.h>
|
||||
|
@ -3911,6 +3939,7 @@ static JSFunctionSpec shell_functions[] = {
|
|||
JS_FN("parse", Parse, 1,0),
|
||||
JS_FN("timeout", Timeout, 1,0),
|
||||
JS_FN("elapsed", Elapsed, 0,0),
|
||||
JS_FN("parent", Parent, 1,0),
|
||||
JS_FS_END
|
||||
};
|
||||
|
||||
|
@ -4018,7 +4047,8 @@ static const char *const shell_help_messages[] = {
|
|||
"timeout([seconds])\n"
|
||||
" Get/Set the limit in seconds for the execution time for the current context.\n"
|
||||
" A negative value (default) means that the execution time is unlimited.",
|
||||
"elapsed() Execution time elapsed for the current context.\n",
|
||||
"elapsed() Execution time elapsed for the current context.",
|
||||
"parent(obj) Returns the parent of obj.\n",
|
||||
};
|
||||
|
||||
/* Help messages must match shell functions. */
|
||||
|
@ -4980,6 +5010,13 @@ main(int argc, char **argv, char **envp)
|
|||
argc--;
|
||||
argv++;
|
||||
|
||||
#ifdef XP_WIN
|
||||
// Set the timer calibration delay count to 0 so we get high
|
||||
// resolution right away, which we need for precise benchmarking.
|
||||
extern int CALIBRATION_DELAY_COUNT;
|
||||
CALIBRATION_DELAY_COUNT = 0;
|
||||
#endif
|
||||
|
||||
rt = JS_NewRuntime(64L * 1024L * 1024L);
|
||||
if (!rt)
|
||||
return 1;
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
|
||||
gTestfile = 'regress-313080.js';
|
||||
|
||||
var summary = "Regression - Do not crash calling __proto__, __parent__";
|
||||
var summary = "Regression - Do not crash calling __proto__";
|
||||
var BUGNUMBER = 313080;
|
||||
var actual = 'No Crash';
|
||||
var expect = 'No Crash';
|
||||
|
@ -48,7 +48,6 @@ START(summary);
|
|||
try
|
||||
{
|
||||
<element/>.__proto__();
|
||||
<element/>.__parent__();
|
||||
<element/>.function::__proto__();
|
||||
}
|
||||
catch(e)
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
var gTestfile = '7.4-01.js';
|
||||
//-----------------------------------------------------------------------------
|
||||
var BUGNUMBER = 475834;
|
||||
var summary = ' /**/ comments with newlines in them do not act as line breaks';
|
||||
var summary = ' /**/ comments with newlines in them must act as line breaks';
|
||||
var actual = '';
|
||||
var expect = '';
|
||||
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
// Any copyright is dedicated to the Public Domain.
|
||||
// http://creativecommons.org/licenses/publicdomain/
|
||||
|
||||
load("ecma_5/Object/defineProperty-setup.js");
|
||||
runDictionaryPropertyPresentTestsFraction(1, 8);
|
|
@ -0,0 +1,5 @@
|
|||
// Any copyright is dedicated to the Public Domain.
|
||||
// http://creativecommons.org/licenses/publicdomain/
|
||||
|
||||
load("ecma_5/Object/defineProperty-setup.js");
|
||||
runDictionaryPropertyPresentTestsFraction(2, 8);
|
|
@ -0,0 +1,5 @@
|
|||
// Any copyright is dedicated to the Public Domain.
|
||||
// http://creativecommons.org/licenses/publicdomain/
|
||||
|
||||
load("ecma_5/Object/defineProperty-setup.js");
|
||||
runDictionaryPropertyPresentTestsFraction(3, 8);
|
|
@ -0,0 +1,5 @@
|
|||
// Any copyright is dedicated to the Public Domain.
|
||||
// http://creativecommons.org/licenses/publicdomain/
|
||||
|
||||
load("ecma_5/Object/defineProperty-setup.js");
|
||||
runDictionaryPropertyPresentTestsFraction(4, 8);
|
|
@ -0,0 +1,5 @@
|
|||
// Any copyright is dedicated to the Public Domain.
|
||||
// http://creativecommons.org/licenses/publicdomain/
|
||||
|
||||
load("ecma_5/Object/defineProperty-setup.js");
|
||||
runDictionaryPropertyPresentTestsFraction(5, 8);
|
|
@ -0,0 +1,5 @@
|
|||
// Any copyright is dedicated to the Public Domain.
|
||||
// http://creativecommons.org/licenses/publicdomain/
|
||||
|
||||
load("ecma_5/Object/defineProperty-setup.js");
|
||||
runDictionaryPropertyPresentTestsFraction(6, 8);
|
|
@ -0,0 +1,5 @@
|
|||
// Any copyright is dedicated to the Public Domain.
|
||||
// http://creativecommons.org/licenses/publicdomain/
|
||||
|
||||
load("ecma_5/Object/defineProperty-setup.js");
|
||||
runDictionaryPropertyPresentTestsFraction(7, 8);
|
|
@ -0,0 +1,5 @@
|
|||
// Any copyright is dedicated to the Public Domain.
|
||||
// http://creativecommons.org/licenses/publicdomain/
|
||||
|
||||
load("ecma_5/Object/defineProperty-setup.js");
|
||||
runDictionaryPropertyPresentTestsFraction(8, 8);
|
|
@ -0,0 +1,5 @@
|
|||
// Any copyright is dedicated to the Public Domain.
|
||||
// http://creativecommons.org/licenses/publicdomain/
|
||||
|
||||
load("ecma_5/Object/defineProperty-setup.js");
|
||||
runNonTerminalPropertyPresentTestsFraction(1, 8);
|
|
@ -0,0 +1,5 @@
|
|||
// Any copyright is dedicated to the Public Domain.
|
||||
// http://creativecommons.org/licenses/publicdomain/
|
||||
|
||||
load("ecma_5/Object/defineProperty-setup.js");
|
||||
runNonTerminalPropertyPresentTestsFraction(2, 8);
|
|
@ -0,0 +1,5 @@
|
|||
// Any copyright is dedicated to the Public Domain.
|
||||
// http://creativecommons.org/licenses/publicdomain/
|
||||
|
||||
load("ecma_5/Object/defineProperty-setup.js");
|
||||
runNonTerminalPropertyPresentTestsFraction(3, 8);
|
|
@ -0,0 +1,5 @@
|
|||
// Any copyright is dedicated to the Public Domain.
|
||||
// http://creativecommons.org/licenses/publicdomain/
|
||||
|
||||
load("ecma_5/Object/defineProperty-setup.js");
|
||||
runNonTerminalPropertyPresentTestsFraction(4, 8);
|
|
@ -0,0 +1,5 @@
|
|||
// Any copyright is dedicated to the Public Domain.
|
||||
// http://creativecommons.org/licenses/publicdomain/
|
||||
|
||||
load("ecma_5/Object/defineProperty-setup.js");
|
||||
runNonTerminalPropertyPresentTestsFraction(5, 8);
|
|
@ -0,0 +1,5 @@
|
|||
// Any copyright is dedicated to the Public Domain.
|
||||
// http://creativecommons.org/licenses/publicdomain/
|
||||
|
||||
load("ecma_5/Object/defineProperty-setup.js");
|
||||
runNonTerminalPropertyPresentTestsFraction(6, 8);
|
|
@ -0,0 +1,5 @@
|
|||
// Any copyright is dedicated to the Public Domain.
|
||||
// http://creativecommons.org/licenses/publicdomain/
|
||||
|
||||
load("ecma_5/Object/defineProperty-setup.js");
|
||||
runNonTerminalPropertyPresentTestsFraction(7, 8);
|
|
@ -0,0 +1,5 @@
|
|||
// Any copyright is dedicated to the Public Domain.
|
||||
// http://creativecommons.org/licenses/publicdomain/
|
||||
|
||||
load("ecma_5/Object/defineProperty-setup.js");
|
||||
runNonTerminalPropertyPresentTestsFraction(8, 8);
|
|
@ -578,7 +578,7 @@ TestRunner.prototype =
|
|||
print("Starting test with old descriptor " + old.toSource() + "...");
|
||||
|
||||
for (var j = 0, sz2 = VALID_DESCRIPTORS.length; j < sz2; j++)
|
||||
self._runSinglePropertyPresentTest(old, VALID_DESCRIPTORS[j]);
|
||||
self._runSinglePropertyPresentTest(old, VALID_DESCRIPTORS[j], []);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -587,6 +587,107 @@ TestRunner.prototype =
|
|||
" completed!");
|
||||
},
|
||||
|
||||
runNonTerminalPropertyPresentTestsFraction:
|
||||
function runNonTerminalPropertyPresentTestsFraction(part, parts)
|
||||
{
|
||||
var self = this;
|
||||
|
||||
/*
|
||||
* A plain old property to define on the object before redefining the
|
||||
* originally-added property, to test redefinition of a property that's
|
||||
* not also lastProperty. NB: we could loop over every possible
|
||||
* descriptor here if we wanted, even try adding more than one, but we'd
|
||||
* hit cubic complexity and worse, and SpiderMonkey only distinguishes by
|
||||
* the mere presence of the middle property, not its precise details.
|
||||
*/
|
||||
var middleDefines =
|
||||
[{
|
||||
property: "middle",
|
||||
descriptor:
|
||||
{ value: 17, writable: true, configurable: true, enumerable: true }
|
||||
}];
|
||||
|
||||
function nonTerminalPropertyPresentTests()
|
||||
{
|
||||
print("Running non-terminal already-present tests now...");
|
||||
|
||||
var total = VALID_DESCRIPTORS.length;
|
||||
var start = Math.floor((part - 1) / parts * total);
|
||||
var end = Math.floor(part / parts * total);
|
||||
|
||||
for (var i = start; i < end; i++)
|
||||
{
|
||||
var old = VALID_DESCRIPTORS[i];
|
||||
print("Starting test with old descriptor " + old.toSource() + "...");
|
||||
|
||||
for (var j = 0, sz2 = VALID_DESCRIPTORS.length; j < sz2; j++)
|
||||
{
|
||||
self._runSinglePropertyPresentTest(old, VALID_DESCRIPTORS[j],
|
||||
middleDefines);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this._runTestSet(nonTerminalPropertyPresentTests,
|
||||
"Non-terminal property-present fraction " +
|
||||
part + " of " + parts + " completed!");
|
||||
},
|
||||
|
||||
runDictionaryPropertyPresentTestsFraction:
|
||||
function runDictionaryPropertyPresentTestsFraction(part, parts)
|
||||
{
|
||||
var self = this;
|
||||
|
||||
/*
|
||||
* Add and readd properties such that the scope for the object is in
|
||||
* dictionary mode.
|
||||
*/
|
||||
var middleDefines =
|
||||
[
|
||||
{
|
||||
property: "mid1",
|
||||
descriptor:
|
||||
{ value: 17, writable: true, configurable: true, enumerable: true }
|
||||
},
|
||||
{
|
||||
property: "mid2",
|
||||
descriptor:
|
||||
{ value: 17, writable: true, configurable: true, enumerable: true }
|
||||
},
|
||||
{
|
||||
property: "mid1",
|
||||
descriptor:
|
||||
{ get: function g() { }, set: function s(v){}, configurable: false,
|
||||
enumerable: true }
|
||||
},
|
||||
];
|
||||
|
||||
function dictionaryPropertyPresentTests()
|
||||
{
|
||||
print("Running dictionary already-present tests now...");
|
||||
|
||||
var total = VALID_DESCRIPTORS.length;
|
||||
var start = Math.floor((part - 1) / parts * total);
|
||||
var end = Math.floor(part / parts * total);
|
||||
|
||||
for (var i = start; i < end; i++)
|
||||
{
|
||||
var old = VALID_DESCRIPTORS[i];
|
||||
print("Starting test with old descriptor " + old.toSource() + "...");
|
||||
|
||||
for (var j = 0, sz2 = VALID_DESCRIPTORS.length; j < sz2; j++)
|
||||
{
|
||||
self._runSinglePropertyPresentTest(old, VALID_DESCRIPTORS[j],
|
||||
middleDefines);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this._runTestSet(dictionaryPropertyPresentTests,
|
||||
"Dictionary property-present fraction " +
|
||||
part + " of " + parts + " completed!");
|
||||
},
|
||||
|
||||
|
||||
// HELPERS
|
||||
|
||||
|
@ -600,7 +701,7 @@ TestRunner.prototype =
|
|||
print("Starting test with old descriptor " + old.toSource() + "...");
|
||||
|
||||
for (var j = 0, sz2 = VALID_DESCRIPTORS.length; j < sz2; j++)
|
||||
this._runSinglePropertyPresentTest(old, VALID_DESCRIPTORS[j]);
|
||||
this._runSinglePropertyPresentTest(old, VALID_DESCRIPTORS[j], []);
|
||||
}
|
||||
},
|
||||
_runTestSet: function _runTestSet(fun, completeMessage)
|
||||
|
@ -724,7 +825,8 @@ TestRunner.prototype =
|
|||
return;
|
||||
}
|
||||
},
|
||||
_runSinglePropertyPresentTest: function _runSinglePropertyPresentTest(old, add)
|
||||
_runSinglePropertyPresentTest:
|
||||
function _runSinglePropertyPresentTest(old, add, middleDefines)
|
||||
{
|
||||
var nativeObj = NativeTest.newObject();
|
||||
var reimplObj = ReimplTest.newObject();
|
||||
|
@ -781,6 +883,35 @@ TestRunner.prototype =
|
|||
return;
|
||||
}
|
||||
|
||||
// Now add (or even readd) however many properties were specified between
|
||||
// the original property to add and the new one, to test redefining
|
||||
// non-last-properties and properties in scopes in dictionary mode.
|
||||
for (var i = 0, sz = middleDefines.length; i < sz; i++)
|
||||
{
|
||||
var middle = middleDefines[i];
|
||||
var prop = middle.property;
|
||||
var desc = middle.descriptor;
|
||||
|
||||
try
|
||||
{
|
||||
NativeTest.defineProperty(nativeObj, prop, desc);
|
||||
ReimplTest.defineProperty(reimplObj, prop, desc);
|
||||
}
|
||||
catch (e)
|
||||
{
|
||||
this._log("failure defining middle descriptor: " + desc.toSource() +
|
||||
", error " + e);
|
||||
return;
|
||||
}
|
||||
|
||||
// Sanity check
|
||||
var nativeDesc = NativeTest.getDescriptor(nativeObj, prop);
|
||||
var reimplDesc = ReimplTest.getDescriptor(reimplObj, prop);
|
||||
|
||||
compareDescriptors(nativeDesc, reimplDesc);
|
||||
compareDescriptors(nativeDesc, desc);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
NativeTest.defineProperty(nativeObj, "foo", add);
|
||||
|
@ -900,3 +1031,72 @@ TestRunner.prototype =
|
|||
}
|
||||
}
|
||||
};
|
||||
|
||||
function runDictionaryPropertyPresentTestsFraction(PART, PARTS)
|
||||
{
|
||||
var testfile =
|
||||
'15.2.3.6-dictionary-redefinition-' + PART + '-of-' + PARTS + '.js';
|
||||
var BUGNUMBER = 560566;
|
||||
var summary =
|
||||
'ES5 Object.defineProperty(O, P, Attributes): dictionary redefinition ' +
|
||||
PART + ' of ' + PARTS;
|
||||
|
||||
print(BUGNUMBER + ": " + summary);
|
||||
|
||||
try
|
||||
{
|
||||
new TestRunner().runDictionaryPropertyPresentTestsFraction(PART, PARTS);
|
||||
}
|
||||
catch (e)
|
||||
{
|
||||
throw "Error thrown during testing: " + e +
|
||||
" at line " + e.lineNumber + "\n" +
|
||||
(e.stack
|
||||
? "Stack: " + e.stack.split("\n").slice(2).join("\n") + "\n"
|
||||
: "");
|
||||
}
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(true, true);
|
||||
|
||||
print("Tests complete!");
|
||||
}
|
||||
|
||||
function runNonTerminalPropertyPresentTestsFraction(PART, PARTS)
|
||||
{
|
||||
var PART = 1, PARTS = 4;
|
||||
|
||||
var gTestfile =
|
||||
'15.2.3.6-middle-redefinition-' + PART + '-of-' + PARTS + '.js';
|
||||
var BUGNUMBER = 560566;
|
||||
var summary =
|
||||
'ES5 Object.defineProperty(O, P, Attributes): middle redefinition ' +
|
||||
PART + ' of ' + PARTS;
|
||||
|
||||
print(BUGNUMBER + ": " + summary);
|
||||
|
||||
|
||||
/**************
|
||||
* BEGIN TEST *
|
||||
**************/
|
||||
|
||||
try
|
||||
{
|
||||
new TestRunner().runNonTerminalPropertyPresentTestsFraction(PART, PARTS);
|
||||
}
|
||||
catch (e)
|
||||
{
|
||||
throw "Error thrown during testing: " + e +
|
||||
" at line " + e.lineNumber + "\n" +
|
||||
(e.stack
|
||||
? "Stack: " + e.stack.split("\n").slice(2).join("\n") + "\n"
|
||||
: "");
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(true, true);
|
||||
|
||||
print("Tests complete!");
|
||||
}
|
||||
|
|
|
@ -11,3 +11,19 @@ skip-if(!xulRuntime.shell) script 15.2.3.6-redefinition-3-of-4.js # uses shell l
|
|||
skip-if(!xulRuntime.shell) script 15.2.3.6-redefinition-4-of-4.js # uses shell load() function
|
||||
script 15.2.3.7-01.js
|
||||
script 15.2.3.14-01.js # does not use reportCompare
|
||||
skip-if(!xulRuntime.shell) script 15.2.3.6-middle-redefinition-1-of-8.js # uses shell load() function
|
||||
skip-if(!xulRuntime.shell) script 15.2.3.6-middle-redefinition-2-of-8.js # uses shell load() function
|
||||
skip-if(!xulRuntime.shell) script 15.2.3.6-middle-redefinition-3-of-8.js # uses shell load() function
|
||||
skip-if(!xulRuntime.shell) script 15.2.3.6-middle-redefinition-4-of-8.js # uses shell load() function
|
||||
skip-if(!xulRuntime.shell) script 15.2.3.6-middle-redefinition-5-of-8.js # uses shell load() function
|
||||
skip-if(!xulRuntime.shell) script 15.2.3.6-middle-redefinition-6-of-8.js # uses shell load() function
|
||||
skip-if(!xulRuntime.shell) script 15.2.3.6-middle-redefinition-7-of-8.js # uses shell load() function
|
||||
skip-if(!xulRuntime.shell) script 15.2.3.6-middle-redefinition-8-of-8.js # uses shell load() function
|
||||
skip-if(!xulRuntime.shell) script 15.2.3.6-dictionary-redefinition-1-of-8.js # uses shell load() function
|
||||
skip-if(!xulRuntime.shell) script 15.2.3.6-dictionary-redefinition-2-of-8.js # uses shell load() function
|
||||
skip-if(!xulRuntime.shell) script 15.2.3.6-dictionary-redefinition-3-of-8.js # uses shell load() function
|
||||
skip-if(!xulRuntime.shell) script 15.2.3.6-dictionary-redefinition-4-of-8.js # uses shell load() function
|
||||
skip-if(!xulRuntime.shell) script 15.2.3.6-dictionary-redefinition-5-of-8.js # uses shell load() function
|
||||
skip-if(!xulRuntime.shell) script 15.2.3.6-dictionary-redefinition-6-of-8.js # uses shell load() function
|
||||
skip-if(!xulRuntime.shell) script 15.2.3.6-dictionary-redefinition-7-of-8.js # uses shell load() function
|
||||
skip-if(!xulRuntime.shell) script 15.2.3.6-dictionary-redefinition-8-of-8.js # uses shell load() function
|
||||
|
|
|
@ -13,7 +13,6 @@ script regress-104077.js
|
|||
script regress-164697.js
|
||||
script regress-178722.js
|
||||
script regress-192465.js
|
||||
script regress-220584.js
|
||||
script regress-225831.js
|
||||
script regress-226078.js
|
||||
script regress-226507.js
|
||||
|
@ -32,7 +31,6 @@ script regress-311161.js
|
|||
script regress-311583.js
|
||||
script regress-311792-01.js
|
||||
script regress-311792-02.js
|
||||
script regress-312278.js
|
||||
script regress-313500.js
|
||||
script regress-313763.js
|
||||
script regress-313803.js
|
||||
|
@ -196,7 +194,6 @@ script regress-452168.js
|
|||
script regress-452178.js
|
||||
script regress-452329.js
|
||||
script regress-452338.js
|
||||
script regress-452372.js
|
||||
script regress-452565.js
|
||||
script regress-453249.js
|
||||
script regress-454040.js
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
var gTestfile = 'regress-164697.js';
|
||||
//-----------------------------------------------------------------------------
|
||||
var BUGNUMBER = 164697;
|
||||
var summary = '(instance.__parent__ == constructor.__parent__)';
|
||||
var summary = '(parent(instance) == parent(constructor))';
|
||||
var actual = '';
|
||||
var expect = '';
|
||||
|
||||
|
@ -61,13 +61,10 @@ runtest('new Function(";")', 'Function');
|
|||
runtest('[]', 'Array');
|
||||
runtest('new Array()', 'Array');
|
||||
|
||||
runtest('""', 'String');
|
||||
runtest('new String()', 'String');
|
||||
|
||||
runtest('true', 'Boolean');
|
||||
runtest('new Boolean()', 'Boolean');
|
||||
|
||||
runtest('1', 'Number');
|
||||
runtest('new Number("1")', 'Number');
|
||||
|
||||
runtest('new Date()', 'Date');
|
||||
|
@ -82,19 +79,23 @@ function runtest(myinstance, myconstructor)
|
|||
var expr;
|
||||
var actual;
|
||||
|
||||
try
|
||||
if (typeof parent === "function")
|
||||
{
|
||||
expr = '(' + myinstance + ').__parent__ == ' +
|
||||
myconstructor + '.__parent__';
|
||||
printStatus(expr);
|
||||
actual = eval(expr).toString();
|
||||
}
|
||||
catch(ex)
|
||||
{
|
||||
actual = ex + '';
|
||||
}
|
||||
try
|
||||
{
|
||||
expr =
|
||||
'parent(' + myinstance + ') == ' +
|
||||
'parent(' + myconstructor + ')';
|
||||
printStatus(expr);
|
||||
actual = eval(expr).toString();
|
||||
}
|
||||
catch(ex)
|
||||
{
|
||||
actual = ex + '';
|
||||
}
|
||||
|
||||
reportCompare(expect, actual, expr);
|
||||
reportCompare(expect, actual, expr);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
|
|
|
@ -1,147 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is JavaScript Engine testing utilities.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corp.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* igor@fastmail.fm, pschwartau@netscape.com
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/*
|
||||
*
|
||||
* Date: 29 Sep 2003
|
||||
* SUMMARY: Testing __parent__ and __proto__ of Script object
|
||||
*
|
||||
* See http://bugzilla.mozilla.org/show_bug.cgi?id=220584
|
||||
*/
|
||||
//-----------------------------------------------------------------------------
|
||||
var gTestfile = 'regress-220584.js';
|
||||
var UBound = 0;
|
||||
var BUGNUMBER = 220584;
|
||||
var summary = 'Testing __parent__ and __proto__ of Script object';
|
||||
var status = '';
|
||||
var statusitems = [];
|
||||
var actual = '';
|
||||
var actualvalues = [];
|
||||
var expect= '';
|
||||
var expectedvalues = [];
|
||||
var s;
|
||||
|
||||
|
||||
// invoke |Script| as a function
|
||||
status = inSection(1);
|
||||
if (typeof Script == 'undefined')
|
||||
{
|
||||
reportCompare("Script not defined, Test skipped.",
|
||||
"Script not defined, Test skipped.",
|
||||
summary);
|
||||
}
|
||||
else
|
||||
{
|
||||
s = Script('1;');
|
||||
actual = s instanceof Object;
|
||||
expect = true;
|
||||
addThis();
|
||||
|
||||
status = inSection(2);
|
||||
actual = (s.__parent__ == undefined) || (s.__parent__ == null);
|
||||
expect = false;
|
||||
addThis();
|
||||
|
||||
status = inSection(3);
|
||||
actual = (s.__proto__ == undefined) || (s.__proto__ == null);
|
||||
expect = false;
|
||||
addThis();
|
||||
|
||||
status = inSection(4);
|
||||
actual = (s + '').length > 0;
|
||||
expect = true;
|
||||
addThis();
|
||||
|
||||
}
|
||||
|
||||
// invoke |Script| as a constructor
|
||||
status = inSection(5);
|
||||
if (typeof Script == 'undefined')
|
||||
{
|
||||
print('Test skipped. Script not defined.');
|
||||
}
|
||||
else
|
||||
{
|
||||
s = new Script('1;');
|
||||
|
||||
actual = s instanceof Object;
|
||||
expect = true;
|
||||
addThis();
|
||||
|
||||
status = inSection(6);
|
||||
actual = (s.__parent__ == undefined) || (s.__parent__ == null);
|
||||
expect = false;
|
||||
addThis();
|
||||
|
||||
status = inSection(7);
|
||||
actual = (s.__proto__ == undefined) || (s.__proto__ == null);
|
||||
expect = false;
|
||||
addThis();
|
||||
|
||||
status = inSection(8);
|
||||
actual = (s + '').length > 0;
|
||||
expect = true;
|
||||
addThis();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
test();
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
function addThis()
|
||||
{
|
||||
statusitems[UBound] = status;
|
||||
actualvalues[UBound] = actual;
|
||||
expectedvalues[UBound] = expect;
|
||||
UBound++;
|
||||
}
|
||||
|
||||
|
||||
function test()
|
||||
{
|
||||
enterFunc('test');
|
||||
printBugNumber(BUGNUMBER);
|
||||
printStatus(summary);
|
||||
|
||||
for (var i=0; i<UBound; i++)
|
||||
{
|
||||
reportCompare(expectedvalues[i], actualvalues[i], statusitems[i]);
|
||||
}
|
||||
|
||||
exitFunc ('test');
|
||||
}
|
|
@ -1,75 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is JavaScript Engine testing utilities.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2005
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s): Igor Bukanov
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
var gTestfile = 'regress-312278.js';
|
||||
//-----------------------------------------------------------------------------
|
||||
var BUGNUMBER = 312278;
|
||||
var summary = 'Do no access GC-ed object in Error.prototype.toSource';
|
||||
var actual = 'No Crash';
|
||||
var expect = 'No Crash';
|
||||
|
||||
printBugNumber(BUGNUMBER);
|
||||
printStatus (summary);
|
||||
|
||||
function wrapInsideWith(obj)
|
||||
{
|
||||
var f;
|
||||
with (obj) {
|
||||
f = function() { }
|
||||
}
|
||||
return f.__parent__;
|
||||
}
|
||||
|
||||
function customToSource()
|
||||
{
|
||||
return "customToSource "+this;
|
||||
}
|
||||
|
||||
Error.prototype.__defineGetter__('message', function() {
|
||||
var obj = {
|
||||
toSource: "something"
|
||||
}
|
||||
obj.__defineGetter__('toSource', function() {
|
||||
gc();
|
||||
return customToSource;
|
||||
});
|
||||
return wrapInsideWith(obj);
|
||||
});
|
||||
|
||||
printStatus(Error.prototype.toSource());
|
||||
|
||||
reportCompare(expect, actual, summary);
|
|
@ -1,64 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is JavaScript Engine testing utilities.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s): Jesse Ruderman
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
var gTestfile = 'regress-452372.js';
|
||||
//-----------------------------------------------------------------------------
|
||||
var BUGNUMBER = 452372;
|
||||
var summary = 'Do not assert with JIT: entry->kpc == (jsbytecode*) atom';
|
||||
var actual = 'No Crash';
|
||||
var expect = 'No Crash';
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
test();
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
function test()
|
||||
{
|
||||
enterFunc ('test');
|
||||
printBugNumber(BUGNUMBER);
|
||||
printStatus (summary);
|
||||
|
||||
jit(true);
|
||||
|
||||
eval("(function() { for (var j = 0; j < 4; ++j) { /x/.__parent__; } })")();
|
||||
|
||||
jit(false);
|
||||
|
||||
reportCompare(expect, actual, summary);
|
||||
|
||||
exitFunc ('test');
|
||||
}
|
|
@ -32,7 +32,6 @@ script regress-355052-03.js
|
|||
script regress-355145.js
|
||||
script regress-355410.js
|
||||
script regress-355512.js
|
||||
script regress-355578.js
|
||||
script regress-355583.js
|
||||
script regress-363040-01.js
|
||||
script regress-363040-02.js
|
||||
|
|
|
@ -1,78 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is JavaScript Engine testing utilities.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2006
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s): shutdown
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
var gTestfile = 'regress-355578.js';
|
||||
//-----------------------------------------------------------------------------
|
||||
var BUGNUMBER = 355578;
|
||||
var summary = 'block object access to dead JSStackFrame';
|
||||
var actual = '';
|
||||
var expect = '';
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
test();
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
function test()
|
||||
{
|
||||
enterFunc ('test');
|
||||
printBugNumber(BUGNUMBER);
|
||||
printStatus (summary);
|
||||
|
||||
var filler = "", rooter = {};
|
||||
for(var i = 0; i < 0x70/2; i++)
|
||||
{
|
||||
filler += "\u5050";
|
||||
}
|
||||
var blkobj = function() { let x; yield function(){}.__parent__; }().next();
|
||||
gc();
|
||||
for(var i = 0; i < 1024; i++)
|
||||
{
|
||||
rooter[i] = filler + i;
|
||||
}
|
||||
try
|
||||
{
|
||||
print(blkobj.x);
|
||||
}
|
||||
catch(ex)
|
||||
{
|
||||
}
|
||||
|
||||
reportCompare(expect, actual, summary);
|
||||
|
||||
exitFunc ('test');
|
||||
}
|
|
@ -58,7 +58,7 @@ function test()
|
|||
try
|
||||
{
|
||||
(function() {
|
||||
let b = function(){}.__parent__;
|
||||
let b = parent(function(){});
|
||||
print(b[1] = throwError);
|
||||
})();
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ function makeWorkerFn(id) {
|
|||
for (n in bar) {
|
||||
for (m in bar[n]) {}
|
||||
}
|
||||
for (n in {}.__parent__) {}
|
||||
for (n in parent({})) {}
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -42,8 +42,8 @@ var actual;
|
|||
expect = actual = 'No crash';
|
||||
if (typeof scatter == 'undefined') {
|
||||
print('Test skipped. scatter not defined.');
|
||||
} else if (!("__parent__" in {})) {
|
||||
print('Test skipped. __parent__ not defined.');
|
||||
} else if (typeof parent === "undefined") {
|
||||
print('Test skipped, no parent() function.');
|
||||
} else {
|
||||
for (let i = 0; i < LOOP_COUNT; i++) {
|
||||
foo = 0;
|
||||
|
|
|
@ -8,9 +8,14 @@ script regress-541255-3.js
|
|||
script regress-541255-4.js
|
||||
script regress-541455.js
|
||||
script regress-546615.js
|
||||
script regress-551763-0.js
|
||||
script regress-551763-1.js
|
||||
script regress-551763-2.js
|
||||
script regress-555246-0.js
|
||||
fails script regress-555246-1.js
|
||||
script regress-559438.js
|
||||
script regress-560101.js
|
||||
script regress-560998-1.js
|
||||
script regress-560998-2.js
|
||||
script regress-563210.js
|
||||
script regress-563221.js
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
(function() {
|
||||
var o = {'arguments': 42};
|
||||
with (o) { // Definitely forces heavyweight.
|
||||
// Note syntax is not a property access.
|
||||
reportCompare(delete arguments, true,
|
||||
"arguments property deletion within with block");
|
||||
}
|
||||
reportCompare('arguments' in o, false,
|
||||
"property deletion observable");
|
||||
})();
|
||||
|
||||
(function() {
|
||||
var o = {'arguments': 42};
|
||||
delete o.arguments;
|
||||
reportCompare('arguments' in o, false,
|
||||
"arguments property deletion with property access syntax");
|
||||
})();
|
||||
|
||||
(function() {
|
||||
var arguments = 42; // Forces heavyweight.
|
||||
reportCompare(delete arguments, false,
|
||||
"arguments variable");
|
||||
})();
|
||||
|
||||
(function() {
|
||||
reportCompare(delete arguments, false, "arguments object");
|
||||
})();
|
|
@ -0,0 +1,4 @@
|
|||
/* Check we can delete arguments in the global space. */
|
||||
arguments = 42;
|
||||
reportCompare(delete arguments, true, "arguments defined as global");
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
/* Check we can't delete a var-declared arguments in global space. */
|
||||
var arguments = 42;
|
||||
reportCompare(delete arguments, false, "arguments defined as global variable");
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/licenses/publicdomain/
|
||||
* Contributors: Gary Kwong and Nicholas Nethercote
|
||||
*/
|
||||
gTestfile = 'regress-563210';
|
||||
|
||||
if (typeof gczeal != 'undefined' && typeof gc != 'undefined') {
|
||||
try
|
||||
{
|
||||
try {
|
||||
__defineGetter__("x", gc)
|
||||
} catch (e) {}
|
||||
gczeal(1)
|
||||
print(x)(Array(-8))
|
||||
}
|
||||
catch(ex)
|
||||
{
|
||||
}
|
||||
}
|
||||
reportCompare("no assertion failure", "no assertion failure", "bug 563210");
|
||||
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
// Any copyright is dedicated to the Public Domain.
|
||||
// http://creativecommons.org/licenses/publicdomain/
|
||||
// Contributor: Jason Orendorff <jorendorff@mozilla.com>
|
||||
|
||||
"" + eval("(function () { if (x) ; else if (y) n(); else { " + Array(10000).join("e;") + " } });");
|
||||
|
||||
if (this.reportCompare)
|
||||
reportCompare(0, 0, "ok");
|
|
@ -1,26 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
|
||||
function mk() {
|
||||
return (function () {});
|
||||
}
|
||||
|
||||
function f() {
|
||||
var j = 55;
|
||||
|
||||
var f = function () {
|
||||
return j;
|
||||
};
|
||||
|
||||
var g = function() {};
|
||||
|
||||
var a = [ mk(), f, g, mk(), mk() ];
|
||||
|
||||
for (var i = 0; i < 5; ++i) {
|
||||
a[i].p = 99;
|
||||
}
|
||||
}
|
||||
|
||||
f();
|
||||
|
||||
for (var i = 0; i < 9; i++)
|
||||
({__parent__: []} = []);
|
|
@ -1,2 +0,0 @@
|
|||
for (var i = 0; i < 9; i++)
|
||||
({__parent__: []} = []);
|
|
@ -223,7 +223,7 @@ interface nsIXPCComponents_Utils : nsISupports
|
|||
*
|
||||
* Returns the global object with which the given object is associated.
|
||||
*
|
||||
* @param obj The JavaScript object whose parent is to be gotten.
|
||||
* @param obj The JavaScript object whose global is to be gotten.
|
||||
* @return the corresponding global.
|
||||
*/
|
||||
void /* JSObject */ getGlobalForObject(/* in JSObject obj */);
|
||||
|
|
|
@ -759,6 +759,24 @@ Options(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
Parent(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
if (argc != 1) {
|
||||
JS_ReportError(cx, "Wrong number of arguments");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
jsval v = JS_ARGV(cx, vp)[0];
|
||||
if (JSVAL_IS_PRIMITIVE(v)) {
|
||||
JS_ReportError(cx, "Only objects have parents!");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
*vp = OBJECT_TO_JSVAL(JS_GetParent(cx, JSVAL_TO_OBJECT(v)));
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSFunctionSpec glob_functions[] = {
|
||||
{"print", Print, 0,0,0},
|
||||
{"readline", ReadLine, 1,0,0},
|
||||
|
@ -774,6 +792,7 @@ static JSFunctionSpec glob_functions[] = {
|
|||
#endif
|
||||
{"clear", Clear, 1,0,0},
|
||||
{"options", Options, 0,0,0},
|
||||
JS_FN("parent", Parent, 1,0),
|
||||
#ifdef DEBUG
|
||||
{"dumpHeap", DumpHeap, 5,0,0},
|
||||
#endif
|
||||
|
|
|
@ -594,9 +594,8 @@ XPC_COW_GetOrSetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp,
|
|||
}
|
||||
|
||||
if (interned_id == GetRTIdByIndex(cx, XPCJSRuntime::IDX_PROTO) ||
|
||||
interned_id == GetRTIdByIndex(cx, XPCJSRuntime::IDX_PARENT) ||
|
||||
interned_id == GetRTIdByIndex(cx, XPCJSRuntime::IDX_EXPOSEDPROPS)) {
|
||||
// No getting or setting __proto__ or __parent__ on my object.
|
||||
// No getting or setting __proto__ on my object.
|
||||
return ThrowException(NS_ERROR_INVALID_ARG, cx); // XXX better error message
|
||||
}
|
||||
|
||||
|
|
|
@ -1382,7 +1382,7 @@ XPCNativeWrapper::CreateExplicitWrapper(JSContext *cx,
|
|||
// parents for it.
|
||||
JS_LockGCThing(cx, wrapperObj);
|
||||
|
||||
// A deep XPCNativeWrapper has a __parent__ chain that mirrors its
|
||||
// A deep XPCNativeWrapper has a parent chain that mirrors its
|
||||
// XPCWrappedNative's chain.
|
||||
if (!MirrorWrappedNativeParent(cx, wrappedNative, &parent))
|
||||
return JS_FALSE;
|
||||
|
|
|
@ -62,7 +62,6 @@ const char* XPCJSRuntime::mStrings[] = {
|
|||
"item", // IDX_ITEM
|
||||
"__proto__", // IDX_PROTO
|
||||
"__iterator__", // IDX_ITERATOR
|
||||
"__parent__", // IDX_PARENT
|
||||
"__exposedProps__" // IDX_EXPOSEDPROPS
|
||||
};
|
||||
|
||||
|
|
|
@ -669,7 +669,6 @@ public:
|
|||
IDX_ITEM ,
|
||||
IDX_PROTO ,
|
||||
IDX_ITERATOR ,
|
||||
IDX_PARENT ,
|
||||
IDX_EXPOSEDPROPS ,
|
||||
IDX_TOTAL_COUNT // just a count of the above
|
||||
};
|
||||
|
@ -3013,7 +3012,7 @@ public:
|
|||
* @param s the native object we're working with
|
||||
* @param type the type of object that s is
|
||||
* @param iid the interface of s that we want
|
||||
* @param scope the default scope to put on the new JSObject's __parent__
|
||||
* @param scope the default scope to put on the new JSObject's parent
|
||||
* chain
|
||||
* @param pErr [out] relevant error code, if any.
|
||||
*/
|
||||
|
@ -3044,8 +3043,7 @@ public:
|
|||
* @param Interface the interface of src that we want
|
||||
* @param cache the wrapper cache for src (may be null, in which case src
|
||||
* will be QI'ed to get the cache)
|
||||
* @param scope the default scope to put on the new JSObject's __parent__
|
||||
* chain
|
||||
* @param scope the default scope to put on the new JSObject's parent chain
|
||||
* @param allowNativeWrapper if true, this method may wrap the resulting
|
||||
* JSObject in an XPCNativeWrapper and return that, as needed.
|
||||
* @param isGlobal
|
||||
|
@ -3100,8 +3098,7 @@ public:
|
|||
* @param type the type of objects in the array
|
||||
* @param iid the interface of each object in the array that we want
|
||||
* @param count the number of items in the array
|
||||
* @param scope the default scope to put on the new JSObjects' __parent__
|
||||
* chain
|
||||
* @param scope the default scope to put on the new JSObjects' parent chain
|
||||
* @param pErr [out] relevant error code, if any.
|
||||
*/
|
||||
static JSBool NativeArray2JS(XPCLazyCallContext& ccx,
|
||||
|
@ -4275,8 +4272,7 @@ public:
|
|||
*
|
||||
* @param ccx the context for the whole procedure
|
||||
* @param variant the variant to convert
|
||||
* @param scope the default scope to put on the new JSObject's __parent__
|
||||
* chain
|
||||
* @param scope the default scope to put on the new JSObject's parent chain
|
||||
* @param pErr [out] relevant error code, if any.
|
||||
* @param pJSVal [out] the resulting jsval.
|
||||
*/
|
||||
|
|
|
@ -1,74 +0,0 @@
|
|||
|
||||
const LOOP_COUNT = 10000;
|
||||
const THREAD_COUNT = 10;
|
||||
|
||||
const nsIThread = Components.interfaces.nsIThread;
|
||||
const ThreadContractID = "@mozilla.org/thread;1";
|
||||
const Thread = new Components.Constructor(ThreadContractID, "nsIThread", "init");
|
||||
|
||||
var foo;
|
||||
var bar;
|
||||
|
||||
function threadProc() {
|
||||
foo = this.id+1;
|
||||
bar[this.id] = {p : 0};
|
||||
var n, m;
|
||||
for(n in bar) {
|
||||
// Uncommenting the line below makes this a lot more likely to deadlock.
|
||||
for(m in bar[n]) {}
|
||||
}
|
||||
// Commented this because I was thinking that the printf impl being called
|
||||
// on so many thread might be contributing to some apparent memory
|
||||
// corruption cases.
|
||||
// print(" printed from other thread "+this.id+". foo is: "+foo);
|
||||
for(n in this.__parent__) /* print(n) */;
|
||||
}
|
||||
|
||||
function runThreads() {
|
||||
print(" printed from main thread. foo is "+foo);
|
||||
|
||||
var threads = new Array(THREAD_COUNT);
|
||||
var i;
|
||||
|
||||
for(i = 0; i < THREAD_COUNT; i++) {
|
||||
var runable = {run : threadProc, id : i};
|
||||
threads[i] = new Thread(runable, 0,
|
||||
nsIThread.PRIORITY_NORMAL,
|
||||
nsIThread.SCOPE_GLOBAL,
|
||||
nsIThread.STATE_JOINABLE);
|
||||
}
|
||||
|
||||
print(" printed from main thread. foo is "+foo);
|
||||
|
||||
// var main_thread = threads[0].currentThread;
|
||||
|
||||
for(i = THREAD_COUNT-1; i >= 0; i--) {
|
||||
// main_thread.sleep(1);
|
||||
threads[i].join();
|
||||
}
|
||||
|
||||
print(" printed from main thread. foo is "+foo);
|
||||
}
|
||||
|
||||
var total_interval = 0;
|
||||
|
||||
for(i = 0; i < LOOP_COUNT; i++) {
|
||||
var start_time = new Date().getTime()/1000;
|
||||
|
||||
foo = 0;
|
||||
bar = new Array(THREAD_COUNT);
|
||||
print("--- loop number "+i);
|
||||
runThreads();
|
||||
|
||||
var end_time = new Date().getTime()/1000;
|
||||
|
||||
var interval = parseInt(100*(end_time - start_time),10)/100;
|
||||
print(" Interval = "+interval+ " seconds.");
|
||||
// ignore first loop
|
||||
if(i) {
|
||||
total_interval += end_time - start_time;
|
||||
var average_interval = parseInt(100*(total_interval / i),10)/100
|
||||
print("Average Interval = "+average_interval+" seconds.");
|
||||
}
|
||||
}
|
||||
|
|
@ -7,10 +7,16 @@
|
|||
.getInterface(Components.interfaces.nsIDOMWindowUtils);
|
||||
ok(utils.getClassName(wrapper) === expected, note);
|
||||
}
|
||||
function check_parent(ok, obj, expected, note) {
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
var utils = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
|
||||
.getInterface(Components.interfaces.nsIDOMWindowUtils);
|
||||
ok(utils.getParent(obj) === expected, note);
|
||||
}
|
||||
function run_test(ok, xpcnw, sjow) {
|
||||
// both wrappers should point to our window: XOW
|
||||
check_wrapper(ok, ok, "Function", "functions are wrapped properly")
|
||||
ok(ok.__parent__ == window, "ok is parented correctly");
|
||||
check_parent(ok, ok, window, "ok is parented correctly");
|
||||
check_wrapper(ok, xpcnw, "XPCCrossOriginWrapper", "XPCNWs are transformed correctly");
|
||||
check_wrapper(ok, sjow, "XPCCrossOriginWrapper", "SJOWs are transformed correctly");
|
||||
|
||||
|
|
|
@ -62,8 +62,7 @@ function COWTests() {
|
|||
var empty = {};
|
||||
isProp(getCOW(empty), "foo", undefined, "empty.foo is undefined");
|
||||
|
||||
const PROPS_TO_TEST = ['foo', '__parent__', '__proto__',
|
||||
'prototype', 'constructor'];
|
||||
const PROPS_TO_TEST = ['foo', '__proto__', 'prototype', 'constructor'];
|
||||
|
||||
var strict = { __exposedProps__: {} };
|
||||
var strictCOW = getCOW(strict);
|
||||
|
|
|
@ -20,11 +20,17 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=366645
|
|||
|
||||
/** Test for Bug 366645 **/
|
||||
|
||||
function getParent(obj) {
|
||||
return window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
|
||||
.getInterface(Components.interfaces.nsIDOMWindowUtils)
|
||||
.getParent(obj);
|
||||
}
|
||||
|
||||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
|
||||
var Cc = Components.classes;
|
||||
var Ci = Components.interfaces;
|
||||
var table = Cc["@mozilla.org/url-classifier/table;1?type=url"].createInstance();
|
||||
var componentScope = table.wrappedJSObject.__parent__;
|
||||
var componentScope = getParent(table.wrappedJSObject);
|
||||
ok(!!componentScope, "unable to get wrapped js object");
|
||||
|
||||
var PROT_EnchashDecrypter = componentScope.PROT_EnchashDecrypter;
|
||||
|
|
|
@ -45,6 +45,18 @@ const Ci = Components.interfaces;
|
|||
|
||||
#expand const CTYPES_TEST_LIB = __CTYPES_TEST_LIB__;
|
||||
|
||||
function getParent(obj, fun)
|
||||
{
|
||||
if (typeof parent === "function")
|
||||
fun(parent(obj));
|
||||
}
|
||||
|
||||
function checkParentIsCTypes(o)
|
||||
{
|
||||
function parentIsCTypes(p) { do_check_true(p === ctypes); }
|
||||
getParent(o, parentIsCTypes);
|
||||
}
|
||||
|
||||
function do_check_throws(f, type, stack)
|
||||
{
|
||||
if (!stack)
|
||||
|
@ -233,16 +245,20 @@ function run_abstract_class_tests()
|
|||
do_check_class(ctypes.CType, "Function");
|
||||
do_check_class(ctypes.CType.prototype, "CType");
|
||||
|
||||
do_check_true(ctypes.CType.__parent__ === ctypes);
|
||||
do_check_true(ctypes.CType.__proto__ === ctypes.__parent__.Function.prototype);
|
||||
do_check_true(ctypes.CType instanceof ctypes.__parent__.Function);
|
||||
checkParentIsCTypes(ctypes.CType);
|
||||
getParent(ctypes, function(p) {
|
||||
do_check_true(Object.getPrototypeOf(ctypes.CType) === p.Function.prototype);
|
||||
do_check_true(ctypes.CType instanceof p.Function);
|
||||
});
|
||||
|
||||
do_check_true(ctypes.CType.hasOwnProperty("prototype"));
|
||||
do_check_throws(function() { ctypes.CType.prototype(); }, Error);
|
||||
do_check_throws(function() { new ctypes.CType.prototype() }, Error);
|
||||
do_check_true(ctypes.CType.prototype.__parent__ === ctypes);
|
||||
do_check_true(ctypes.CType.prototype.__proto__ === ctypes.__parent__.Function.prototype);
|
||||
do_check_true(ctypes.CType.prototype instanceof ctypes.__parent__.Function);
|
||||
checkParentIsCTypes(ctypes.CType.prototype);
|
||||
getParent(ctypes, function(p) {
|
||||
do_check_true(Object.getPrototypeOf(ctypes.CType.prototype) === p.Function.prototype);
|
||||
do_check_true(ctypes.CType.prototype instanceof p.Function);
|
||||
});
|
||||
do_check_true(ctypes.CType.prototype.hasOwnProperty("constructor"));
|
||||
do_check_true(ctypes.CType.prototype.constructor === ctypes.CType);
|
||||
|
||||
|
@ -270,13 +286,15 @@ function run_abstract_class_tests()
|
|||
do_check_class(ctypes.CData, "Function");
|
||||
do_check_class(ctypes.CData.prototype, "CData");
|
||||
|
||||
do_check_true(ctypes.CData.__parent__ === ctypes);
|
||||
checkParentIsCTypes(ctypes.CData);
|
||||
do_check_true(ctypes.CData.__proto__ === ctypes.CType.prototype);
|
||||
do_check_true(ctypes.CData instanceof ctypes.CType);
|
||||
|
||||
do_check_true(ctypes.CData.hasOwnProperty("prototype"));
|
||||
do_check_true(ctypes.CData.prototype.__parent__ === ctypes);
|
||||
do_check_true(ctypes.CData.prototype.__proto__ === ctypes.__parent__.Object.prototype);
|
||||
checkParentIsCTypes(ctypes.CData.prototype);
|
||||
getParent(ctypes, function(p) {
|
||||
do_check_true(Object.getPrototypeOf(ctypes.CData.prototype) === p.Object.prototype);
|
||||
});
|
||||
do_check_true(ctypes.CData.prototype.hasOwnProperty("constructor"));
|
||||
do_check_true(ctypes.CData.prototype.constructor === ctypes.CData);
|
||||
|
||||
|
@ -303,12 +321,14 @@ function run_Int64_tests() {
|
|||
do_check_class(ctypes.Int64, "Function");
|
||||
do_check_class(ctypes.Int64.prototype, "Int64");
|
||||
|
||||
do_check_true(ctypes.Int64.__parent__ === ctypes);
|
||||
do_check_true(ctypes.Int64.__proto__ === ctypes.__parent__.Function.prototype);
|
||||
checkParentIsCTypes(ctypes.Int64);
|
||||
getParent(ctypes, function(p) {
|
||||
do_check_true(Object.getPrototypeOf(ctypes.Int64) === p.Function.prototype);
|
||||
do_check_true(Object.getPrototypeOf(ctypes.Int64.prototype) === p.Object.prototype);
|
||||
});
|
||||
|
||||
do_check_true(ctypes.Int64.hasOwnProperty("prototype"));
|
||||
do_check_true(ctypes.Int64.prototype.__parent__ === ctypes);
|
||||
do_check_true(ctypes.Int64.prototype.__proto__ === ctypes.__parent__.Object.prototype);
|
||||
checkParentIsCTypes(ctypes.Int64.prototype);
|
||||
do_check_true(ctypes.Int64.prototype.hasOwnProperty("constructor"));
|
||||
do_check_true(ctypes.Int64.prototype.constructor === ctypes.Int64);
|
||||
|
||||
|
@ -326,7 +346,7 @@ function run_Int64_tests() {
|
|||
do_check_throws(function() { ctypes.Int64.prototype.toSource(); }, Error);
|
||||
|
||||
let i = ctypes.Int64(0);
|
||||
do_check_true(i.__parent__ === ctypes);
|
||||
checkParentIsCTypes(i);
|
||||
do_check_true(i.__proto__ === ctypes.Int64.prototype);
|
||||
do_check_true(i instanceof ctypes.Int64);
|
||||
|
||||
|
@ -480,12 +500,16 @@ function run_UInt64_tests() {
|
|||
do_check_class(ctypes.UInt64, "Function");
|
||||
do_check_class(ctypes.UInt64.prototype, "UInt64");
|
||||
|
||||
do_check_true(ctypes.UInt64.__parent__ === ctypes);
|
||||
do_check_true(ctypes.UInt64.__proto__ === ctypes.__parent__.Function.prototype);
|
||||
checkParentIsCTypes(ctypes.UInt64);
|
||||
getParent(ctypes, function(p) {
|
||||
do_check_true(Object.getPrototypeOf(ctypes.UInt64) === p.Function.prototype);
|
||||
});
|
||||
|
||||
do_check_true(ctypes.UInt64.hasOwnProperty("prototype"));
|
||||
do_check_true(ctypes.UInt64.prototype.__parent__ === ctypes);
|
||||
do_check_true(ctypes.UInt64.prototype.__proto__ === ctypes.__parent__.Object.prototype);
|
||||
checkParentIsCTypes(ctypes.UInt64.prototype);
|
||||
getParent(ctypes, function(p) {
|
||||
do_check_true(Object.getPrototypeOf(ctypes.UInt64.prototype) === p.Object.prototype);
|
||||
});
|
||||
do_check_true(ctypes.UInt64.prototype.hasOwnProperty("constructor"));
|
||||
do_check_true(ctypes.UInt64.prototype.constructor === ctypes.UInt64);
|
||||
|
||||
|
@ -503,7 +527,7 @@ function run_UInt64_tests() {
|
|||
do_check_throws(function() { ctypes.UInt64.prototype.toSource(); }, Error);
|
||||
|
||||
let i = ctypes.UInt64(0);
|
||||
do_check_true(i.__parent__ === ctypes);
|
||||
checkParentIsCTypes(i);
|
||||
do_check_true(i.__proto__ === ctypes.UInt64.prototype);
|
||||
do_check_true(i instanceof ctypes.UInt64);
|
||||
|
||||
|
@ -720,11 +744,11 @@ function run_basic_class_tests(t)
|
|||
do_check_class(t, "CType");
|
||||
do_check_class(t.prototype, "CData");
|
||||
|
||||
do_check_true(t.__parent__ === ctypes);
|
||||
checkParentIsCTypes(t);
|
||||
do_check_true(t.__proto__ === ctypes.CType.prototype);
|
||||
do_check_true(t instanceof ctypes.CType);
|
||||
|
||||
do_check_true(t.prototype.__parent__ === ctypes);
|
||||
checkParentIsCTypes(t.prototype);
|
||||
do_check_true(t.prototype.__proto__ === ctypes.CData.prototype);
|
||||
do_check_true(t.prototype instanceof ctypes.CData);
|
||||
do_check_true(t.prototype.constructor === t);
|
||||
|
@ -740,7 +764,7 @@ function run_basic_class_tests(t)
|
|||
// Test that an instance 'd' of 't' is a CData.
|
||||
let d = t();
|
||||
do_check_class(d, "CData");
|
||||
do_check_true(d.__parent__ === ctypes);
|
||||
checkParentIsCTypes(d);
|
||||
do_check_true(d.__proto__ === t.prototype);
|
||||
do_check_true(d instanceof t);
|
||||
do_check_true(d.constructor === t);
|
||||
|
@ -1265,11 +1289,13 @@ function run_type_ctor_class_tests(c, t, t2, props, fns, instanceProps, instance
|
|||
do_check_class(c, "Function");
|
||||
do_check_class(c.prototype, "CType");
|
||||
|
||||
do_check_true(c.__parent__ === ctypes);
|
||||
do_check_true(c.__proto__ === ctypes.__parent__.Function.prototype);
|
||||
do_check_true(c instanceof ctypes.__parent__.Function);
|
||||
checkParentIsCTypes(c);
|
||||
getParent(ctypes, function(p) {
|
||||
do_check_true(Object.getPrototypeOf(c) === p.Function.prototype);
|
||||
do_check_true(c instanceof p.Function);
|
||||
});
|
||||
|
||||
do_check_true(c.prototype.__parent__ === ctypes);
|
||||
checkParentIsCTypes(c.prototype);
|
||||
do_check_true(c.prototype.__proto__ === ctypes.CType.prototype);
|
||||
do_check_true(c.prototype instanceof ctypes.CType);
|
||||
do_check_true(c.prototype.constructor === c);
|
||||
|
@ -1291,18 +1317,18 @@ function run_type_ctor_class_tests(c, t, t2, props, fns, instanceProps, instance
|
|||
do_check_class(t, "CType");
|
||||
do_check_class(t.prototype, "CData");
|
||||
|
||||
do_check_true(t.__parent__ === ctypes);
|
||||
checkParentIsCTypes(t);
|
||||
do_check_true(t.__proto__ === c.prototype);
|
||||
do_check_true(t instanceof c);
|
||||
|
||||
do_check_true(t.prototype.__parent__ === ctypes);
|
||||
checkParentIsCTypes(t.prototype);
|
||||
do_check_class(t.prototype.__proto__, "CData");
|
||||
// 't.prototype.__proto__' is the common ancestor of all types constructed
|
||||
// from 'c'; while not available from 'c' directly, it should be identically
|
||||
// equal to 't2.prototype.__proto__' where 't2' is a different CType
|
||||
// constructed from 'c'.
|
||||
do_check_true(t.prototype.__proto__ === t2.prototype.__proto__);
|
||||
do_check_true(t.prototype.__proto__.__parent__ === ctypes);
|
||||
checkParentIsCTypes(Object.getPrototypeOf(t.prototype));
|
||||
do_check_true(t.prototype.__proto__.__proto__ === ctypes.CData.prototype);
|
||||
do_check_true(t.prototype instanceof ctypes.CData);
|
||||
do_check_true(t.prototype.constructor === t);
|
||||
|
@ -1337,7 +1363,7 @@ function run_type_ctor_class_tests(c, t, t2, props, fns, instanceProps, instance
|
|||
if (t.__proto__ != ctypes.FunctionType.prototype) {
|
||||
let d = t();
|
||||
do_check_class(d, "CData");
|
||||
do_check_true(d.__parent__ === ctypes);
|
||||
checkParentIsCTypes(d);
|
||||
do_check_true(d.__proto__ === t.prototype);
|
||||
do_check_true(d instanceof t);
|
||||
do_check_true(d.constructor === t);
|
||||
|
|
|
@ -18,11 +18,17 @@ mochitest framework.
|
|||
<script class="testbody" type="text/javascript">
|
||||
<![CDATA[
|
||||
|
||||
function getParent(obj) {
|
||||
return window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
|
||||
.getInterface(Components.interfaces.nsIDOMWindowUtils)
|
||||
.getParent(obj);
|
||||
}
|
||||
|
||||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
|
||||
var Cc = Components.classes;
|
||||
var Ci = Components.interfaces;
|
||||
var table = Cc["@mozilla.org/url-classifier/table;1?type=url"].createInstance();
|
||||
var componentScope = table.wrappedJSObject.__parent__;
|
||||
var componentScope = getParent(table.wrappedJSObject);
|
||||
ok(!!componentScope, "unable to get wrapped js object");
|
||||
|
||||
////// Test PROT_EnchashDecrypter methods //////
|
||||
|
|
Загрузка…
Ссылка в новой задаче