Merge tracemonkey to mozilla-central.

This commit is contained in:
Robert Sayre 2010-05-06 08:50:41 -04:00
Родитель 00ccdd4013 470ce2375e
Коммит 39676ac642
76 изменённых файлов: 1021 добавлений и 1050 удалений

Просмотреть файл

@ -3101,10 +3101,10 @@ nsXULPrototypeScript::Compile(const PRUnichar* aText,
// //
// Compiling it using (for example) the first document's global // Compiling it using (for example) the first document's global
// object would cause JS to keep a reference via the __proto__ or // object would cause JS to keep a reference via the __proto__ or
// __parent__ pointer to the first document's global. If that // parent pointer to the first document's global. If that happened,
// happened, our script object would reference the first document, // our script object would reference the first document, and the
// and the first document would indirectly reference the prototype // first document would indirectly reference the prototype document
// document because it keeps the prototype cache alive. Circularity! // because it keeps the prototype cache alive. Circularity!
nsresult rv; nsresult rv;
// Use the prototype document's special context // Use the prototype document's special context

Просмотреть файл

@ -1266,3 +1266,65 @@ nsDOMWindowUtils::GetVisitedDependentComputedStyle(
return rv; 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 nsITransferable;
interface nsIQueryContentEventResult; interface nsIQueryContentEventResult;
[scriptable, uuid(22a62b54-bcf5-422a-a329-fed4de5e78b2)] [scriptable, uuid(352ff0af-bb38-496a-a067-b54771168d6d)]
interface nsIDOMWindowUtils : nsISupports { interface nsIDOMWindowUtils : nsISupports {
/** /**
@ -655,4 +655,12 @@ interface nsIDOMWindowUtils : nsISupports {
AString getVisitedDependentComputedStyle(in nsIDOMElement aElement, AString getVisitedDependentComputedStyle(in nsIDOMElement aElement,
in AString aPseudoElement, in AString aPseudoElement,
in AString aPropertyName); 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; return;
} }
print("* Object type: "+typeof obj+"\n"); 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) { switch(typeof obj) {
case "object": case "object":
print("* Prototype chain: "); 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. // Create a hash of FieldInfo objects to stash on the type object.
FieldInfoHash* fields(new FieldInfoHash); FieldInfoHash* fields(new FieldInfoHash);
if (!fields || !fields->init(len)) { if (!fields || !fields->init(len)) {
delete fields;
JS_ReportOutOfMemory(cx); JS_ReportOutOfMemory(cx);
delete fields;
return JS_FALSE; return JS_FALSE;
} }
// Stash the FieldInfo hash in a reserved slot now, for GC safety of its // Stash the FieldInfo hash in a reserved slot now, for GC safety of its
// constituents. // constituents.
if (!JS_SetReservedSlot(cx, typeObj, SLOT_FIELDINFO, if (!JS_SetReservedSlot(cx, typeObj, SLOT_FIELDINFO,
PRIVATE_TO_JSVAL(fields))) PRIVATE_TO_JSVAL(fields))) {
delete fields;
return JS_FALSE; return JS_FALSE;
}
// Process the field types. // Process the field types.
size_t structSize, structAlign; size_t structSize, structAlign;

Просмотреть файл

@ -1345,7 +1345,6 @@ static JSStdName standard_class_names[] = {
static JSStdName object_prototype_names[] = { static JSStdName object_prototype_names[] = {
/* Object.prototype properties (global delegates to Object.prototype). */ /* Object.prototype properties (global delegates to Object.prototype). */
{js_InitObjectClass, EAGER_ATOM(proto), NULL}, {js_InitObjectClass, EAGER_ATOM(proto), NULL},
{js_InitObjectClass, EAGER_ATOM(parent), NULL},
#if JS_HAS_TOSOURCE #if JS_HAS_TOSOURCE
{js_InitObjectClass, EAGER_ATOM(toSource), NULL}, {js_InitObjectClass, EAGER_ATOM(toSource), NULL},
#endif #endif
@ -4237,12 +4236,11 @@ js_generic_fast_native_method_dispatcher(JSContext *cx, uintN argc, jsval *vp)
fs = (JSFunctionSpec *) JSVAL_TO_PRIVATE(fsv); fs = (JSFunctionSpec *) JSVAL_TO_PRIVATE(fsv);
JS_ASSERT((~fs->flags & (JSFUN_FAST_NATIVE | JSFUN_GENERIC_NATIVE)) == 0); JS_ASSERT((~fs->flags & (JSFUN_FAST_NATIVE | JSFUN_GENERIC_NATIVE)) == 0);
/* if (argc < 1) {
* We know that vp[2] is valid because JS_DefineFunctions, which is our js_ReportMissingArg(cx, vp, 0);
* only (indirect) referrer, defined us as requiring at least one argument return JS_FALSE;
* (notice how it passes fs->nargs + 1 as the next-to-last argument to }
* JS_DefineFunction).
*/
if (JSVAL_IS_PRIMITIVE(vp[2])) { if (JSVAL_IS_PRIMITIVE(vp[2])) {
/* /*
* Make sure that this is an object or null, as required by the generic * 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)) if (!js_ComputeThis(cx, vp + 2))
return JS_FALSE; return JS_FALSE;
/*
* Protect against argc underflowing. By calling js_ComputeThis, we made /* Clear the last parameter in case too few arguments were passed. */
* it as if the static was called with one parameter, the explicit |this| vp[2 + --argc] = JSVAL_VOID;
* object.
*/
if (argc != 0) {
/* Clear the last parameter in case too few arguments were passed. */
vp[2 + --argc] = JSVAL_VOID;
}
native = native =
#ifdef JS_TRACER #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)) == JS_ASSERT((fs->flags & (JSFUN_FAST_NATIVE | JSFUN_GENERIC_NATIVE)) ==
JSFUN_GENERIC_NATIVE); JSFUN_GENERIC_NATIVE);
/* if (argc < 1) {
* We know that argv[0] is valid because JS_DefineFunctions, which is our js_ReportMissingArg(cx, argv - 2, 0);
* only (indirect) referrer, defined us as requiring at least one argument return JS_FALSE;
* (notice how it passes fs->nargs + 1 as the next-to-last argument to }
* JS_DefineFunction).
*/
if (JSVAL_IS_PRIMITIVE(argv[0])) { if (JSVAL_IS_PRIMITIVE(argv[0])) {
/* /*
* Make sure that this is an object or null, as required by the generic * 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_GetTopStackFrame(cx)->thisv = argv[-1];
JS_ASSERT(cx->fp->argv == argv); JS_ASSERT(cx->fp->argv == argv);
/* /* Clear the last parameter in case too few arguments were passed. */
* Protect against argc underflowing. By calling js_ComputeThis, we made argv[--argc] = JSVAL_VOID;
* 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;
}
return fs->call(cx, JSVAL_TO_OBJECT(argv[-1]), argc, argv, rval); return fs->call(cx, JSVAL_TO_OBJECT(argv[-1]), argc, argv, rval);
} }

Просмотреть файл

@ -57,7 +57,8 @@
* setters, it's updated automatically by setDenseArrayLength() and * setters, it's updated automatically by setDenseArrayLength() and
* setDenseArrayCapacity(). There are also no explicit getters, the only * setDenseArrayCapacity(). There are also no explicit getters, the only
* user is TraceRecorder which can access it directly because it's a * 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 * In dense mode, holes in the array are represented by JSVAL_HOLE. The final
* slot in fslots is unused. * slot in fslots is unused.
@ -1273,8 +1274,7 @@ JSClass js_ArrayClass = {
"Array", "Array",
JSCLASS_HAS_RESERVED_SLOTS(2) | JSCLASS_HAS_RESERVED_SLOTS(2) |
JSCLASS_HAS_CACHED_PROTO(JSProto_Array) | JSCLASS_HAS_CACHED_PROTO(JSProto_Array) |
JSCLASS_NEW_ENUMERATE | JSCLASS_NEW_ENUMERATE,
JSCLASS_CONSTRUCT_PROTOTYPE,
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
JS_EnumerateStub, JS_ResolveStub, js_TryValueOf, array_finalize, JS_EnumerateStub, JS_ResolveStub, js_TryValueOf, array_finalize,
array_getObjectOps, NULL, NULL, NULL, array_getObjectOps, NULL, NULL, NULL,

Просмотреть файл

@ -147,7 +147,6 @@ const char *const js_common_atom_names[] = {
js_name_str, /* nameAtom */ js_name_str, /* nameAtom */
js_next_str, /* nextAtom */ js_next_str, /* nextAtom */
js_noSuchMethod_str, /* noSuchMethodAtom */ js_noSuchMethod_str, /* noSuchMethodAtom */
js_parent_str, /* parentAtom */
js_proto_str, /* protoAtom */ js_proto_str, /* protoAtom */
js_set_str, /* setAtom */ js_set_str, /* setAtom */
js_stack_str, /* stackAtom */ js_stack_str, /* stackAtom */
@ -220,7 +219,6 @@ const char js_name_str[] = "name";
const char js_next_str[] = "next"; const char js_next_str[] = "next";
const char js_noSuchMethod_str[] = "__noSuchMethod__"; const char js_noSuchMethod_str[] = "__noSuchMethod__";
const char js_object_str[] = "object"; const char js_object_str[] = "object";
const char js_parent_str[] = "__parent__";
const char js_proto_str[] = "__proto__"; const char js_proto_str[] = "__proto__";
const char js_setter_str[] = "setter"; const char js_setter_str[] = "setter";
const char js_set_str[] = "set"; const char js_set_str[] = "set";

Просмотреть файл

@ -259,7 +259,6 @@ struct JSAtomState {
JSAtom *nameAtom; JSAtom *nameAtom;
JSAtom *nextAtom; JSAtom *nextAtom;
JSAtom *noSuchMethodAtom; JSAtom *noSuchMethodAtom;
JSAtom *parentAtom;
JSAtom *protoAtom; JSAtom *protoAtom;
JSAtom *setAtom; JSAtom *setAtom;
JSAtom *stackAtom; JSAtom *stackAtom;
@ -388,7 +387,6 @@ extern const char js_namespace_str[];
extern const char js_next_str[]; extern const char js_next_str[];
extern const char js_noSuchMethod_str[]; extern const char js_noSuchMethod_str[];
extern const char js_object_str[]; extern const char js_object_str[];
extern const char js_parent_str[];
extern const char js_proto_str[]; extern const char js_proto_str[];
extern const char js_ptagc_str[]; extern const char js_ptagc_str[];
extern const char js_qualifier_str[]; extern const char js_qualifier_str[];

Просмотреть файл

@ -832,10 +832,9 @@ struct JSRuntime {
void *gcExtraRootsData; void *gcExtraRootsData;
/* /*
* Used to serialize cycle checks when setting __proto__ or __parent__ by * Used to serialize cycle checks when setting __proto__ by requesting the
* requesting the GC handle the required cycle detection. If the GC hasn't * GC handle the required cycle detection. If the GC hasn't been poked, it
* been poked, it won't scan for garbage. This member is protected by * won't scan for garbage. This member is protected by rt->gcLock.
* rt->gcLock.
*/ */
JSSetSlotRequest *setSlotRequests; JSSetSlotRequest *setSlotRequests;

Просмотреть файл

@ -49,15 +49,14 @@
#define TYPEOF(cx,v) (JSVAL_IS_NULL(v) ? JSTYPE_NULL : JS_TypeOfValue(cx,v)) #define TYPEOF(cx,v) (JSVAL_IS_NULL(v) ? JSTYPE_NULL : JS_TypeOfValue(cx,v))
using namespace js;
static char dempty[] = "<null>"; static char dempty[] = "<null>";
static char * static char *
jsdtrace_fun_classname(const JSFunction *fun) jsdtrace_fun_classname(const JSFunction *fun)
{ {
return (fun && return (fun && !FUN_INTERPRETED(fun) && !(fun->flags & JSFUN_TRCINFO) && FUN_CLASP(fun))
!FUN_INTERPRETED(fun) &&
!(fun->flags & JSFUN_TRCINFO) &&
FUN_CLASP(fun))
? (char *)FUN_CLASP(fun)->name ? (char *)FUN_CLASP(fun)->name
: dempty; : dempty;
} }
@ -65,9 +64,7 @@ jsdtrace_fun_classname(const JSFunction *fun)
static char * static char *
jsdtrace_filename(JSStackFrame *fp) jsdtrace_filename(JSStackFrame *fp)
{ {
return (fp && fp->script && fp->script->filename) return (fp && fp->script && fp->script->filename) ? (char *)fp->script->filename : dempty;
? (char *)fp->script->filename
: dempty;
} }
static int static int
@ -79,7 +76,7 @@ jsdtrace_fun_linenumber(JSContext *cx, const JSFunction *fun)
return 0; return 0;
} }
int static int
jsdtrace_frame_linenumber(JSContext *cx, JSStackFrame *fp) jsdtrace_frame_linenumber(JSContext *cx, JSStackFrame *fp)
{ {
if (fp && fp->regs) if (fp && fp->regs)
@ -138,13 +135,10 @@ jsdtrace_jsvaltovoid(JSContext *cx, const jsval argval)
static char * static char *
jsdtrace_fun_name(JSContext *cx, const JSFunction *fun) jsdtrace_fun_name(JSContext *cx, const JSFunction *fun)
{ {
JSAtom *atom;
char *name;
if (!fun) if (!fun)
return dempty; return dempty;
atom = fun->atom; JSAtom *atom = fun->atom;
if (!atom) { if (!atom) {
/* /*
* TODO: maybe do more work here to figure out the name of the property * 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; 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; 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. * a number of usually unused lines of code would cause.
*/ */
void void
jsdtrace_function_entry(JSContext *cx, JSStackFrame *fp, const JSFunction *fun) DTrace::enterJSFunImpl(JSContext *cx, JSStackFrame *fp, const JSFunction *fun)
{ {
JAVASCRIPT_FUNCTION_ENTRY( JAVASCRIPT_FUNCTION_ENTRY(jsdtrace_filename(fp), jsdtrace_fun_classname(fun),
jsdtrace_filename(fp), jsdtrace_fun_name(cx, fun));
jsdtrace_fun_classname(fun),
jsdtrace_fun_name(cx, fun)
);
} }
void void
jsdtrace_function_info(JSContext *cx, JSStackFrame *fp, JSStackFrame *dfp, DTrace::handleFunctionInfo(JSContext *cx, JSStackFrame *fp, JSStackFrame *dfp, JSFunction *fun)
JSFunction *fun)
{ {
JAVASCRIPT_FUNCTION_INFO( JAVASCRIPT_FUNCTION_INFO(jsdtrace_filename(fp), jsdtrace_fun_classname(fun),
jsdtrace_filename(fp), jsdtrace_fun_name(cx, fun), jsdtrace_fun_linenumber(cx, fun),
jsdtrace_fun_classname(fun), jsdtrace_filename(dfp), jsdtrace_frame_linenumber(cx, dfp));
jsdtrace_fun_name(cx, fun),
jsdtrace_fun_linenumber(cx, fun),
jsdtrace_filename(dfp),
jsdtrace_frame_linenumber(cx, dfp)
);
} }
void void
jsdtrace_function_args(JSContext *cx, JSStackFrame *fp, const JSFunction *fun, DTrace::handleFunctionArgs(JSContext *cx, JSStackFrame *fp, const JSFunction *fun, jsuint argc,
jsuint argc, jsval *argv) jsval *argv)
{ {
JAVASCRIPT_FUNCTION_ARGS( JAVASCRIPT_FUNCTION_ARGS(jsdtrace_filename(fp), jsdtrace_fun_classname(fun),
jsdtrace_filename(fp), jsdtrace_fun_name(cx, fun), argc, (void *)argv,
jsdtrace_fun_classname(fun), (argc > 0) ? jsdtrace_jsvaltovoid(cx, argv[0]) : 0,
jsdtrace_fun_name(cx, fun), (argc > 1) ? jsdtrace_jsvaltovoid(cx, argv[1]) : 0,
argc, (void *)argv, (argc > 2) ? jsdtrace_jsvaltovoid(cx, argv[2]) : 0,
(argc > 0) ? jsdtrace_jsvaltovoid(cx, argv[0]) : 0, (argc > 3) ? jsdtrace_jsvaltovoid(cx, argv[3]) : 0,
(argc > 1) ? jsdtrace_jsvaltovoid(cx, argv[1]) : 0, (argc > 4) ? jsdtrace_jsvaltovoid(cx, argv[4]) : 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 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( JAVASCRIPT_FUNCTION_RVAL(jsdtrace_filename(fp), jsdtrace_fun_classname(fun),
jsdtrace_filename(fp), jsdtrace_fun_name(cx, fun), jsdtrace_fun_linenumber(cx, fun),
jsdtrace_fun_classname(fun), NULL, jsdtrace_jsvaltovoid(cx, rval));
jsdtrace_fun_name(cx, fun),
jsdtrace_fun_linenumber(cx, fun),
(void *)rval,
jsdtrace_jsvaltovoid(cx, *rval)
);
} }
void void
jsdtrace_function_return(JSContext *cx, JSStackFrame *fp, JSFunction *fun) DTrace::handleFunctionReturn(JSContext *cx, JSStackFrame *fp, JSFunction *fun)
{ {
JAVASCRIPT_FUNCTION_RETURN( JAVASCRIPT_FUNCTION_RETURN(jsdtrace_filename(fp), jsdtrace_fun_classname(fun),
jsdtrace_filename(fp), jsdtrace_fun_name(cx, fun));
jsdtrace_fun_classname(fun),
jsdtrace_fun_name(cx, fun)
);
} }
void void
jsdtrace_object_create_start(JSStackFrame *fp, JSClass *clasp) DTrace::ObjectCreationScope::handleCreationStart()
{ {
JAVASCRIPT_OBJECT_CREATE_START(jsdtrace_filename(fp), (char *)clasp->name); JAVASCRIPT_OBJECT_CREATE_START(jsdtrace_filename(fp), (char *)clasp->name);
} }
void void
jsdtrace_object_create_done(JSStackFrame *fp, JSClass *clasp) DTrace::ObjectCreationScope::handleCreationEnd()
{ {
JAVASCRIPT_OBJECT_CREATE_DONE(jsdtrace_filename(fp), (char *)clasp->name); JAVASCRIPT_OBJECT_CREATE_DONE(jsdtrace_filename(fp), (char *)clasp->name);
} }
void void
jsdtrace_object_create(JSContext *cx, JSClass *clasp, JSObject *obj) DTrace::ObjectCreationScope::handleCreationImpl(JSObject *obj)
{ {
JAVASCRIPT_OBJECT_CREATE( JAVASCRIPT_OBJECT_CREATE(jsdtrace_filename(cx->fp), (char *)clasp->name, (uintptr_t)obj,
jsdtrace_filename(cx->fp), jsdtrace_frame_linenumber(cx, cx->fp));
(char *)clasp->name,
(uintptr_t)obj,
jsdtrace_frame_linenumber(cx, cx->fp)
);
} }
void void
jsdtrace_object_finalize(JSObject *obj) DTrace::finalizeObjectImpl(JSObject *obj)
{ {
JSClass *clasp; JSClass *clasp = obj->getClass();
clasp = obj->getClass();
/* the first arg is NULL - reserved for future use (filename?) */ /* the first arg is NULL - reserved for future use (filename?) */
JAVASCRIPT_OBJECT_FINALIZE(NULL, (char *)clasp->name, (uintptr_t)obj); JAVASCRIPT_OBJECT_FINALIZE(NULL, (char *)clasp->name, (uintptr_t)obj);
} }
void void
jsdtrace_execute_start(JSScript *script) DTrace::ExecutionScope::startExecution()
{ {
JAVASCRIPT_EXECUTE_START( JAVASCRIPT_EXECUTE_START(script->filename ? (char *)script->filename : dempty,
script->filename ? (char *)script->filename : dempty, script->lineno);
script->lineno
);
} }
void void
jsdtrace_execute_done(JSScript *script) DTrace::ExecutionScope::endExecution()
{ {
JAVASCRIPT_EXECUTE_DONE( JAVASCRIPT_EXECUTE_DONE(script->filename ? (char *)script->filename : dempty, script->lineno);
script->filename ? (char *)script->filename : dempty,
script->lineno
);
} }

Просмотреть файл

@ -42,126 +42,139 @@
#ifndef _JSDTRACEF_H #ifndef _JSDTRACEF_H
#define _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 { namespace js {
class DTrace { 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: public:
/* /*
* If |lval| is provided to the enter/exit methods, it is tested to see if * 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. * 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); JSStackFrame *dfp, jsuint argc, jsval *argv, jsval *lval = NULL);
static void exitJSFun(JSContext *cx, JSStackFrame *fp, const JSFunction *fun, static void exitJSFun(JSContext *cx, JSStackFrame *fp, JSFunction *fun, jsval rval,
jsval rval, jsval *lval = NULL); jsval *lval = NULL);
static void finalizeObject(const JSObject *obj); static void finalizeObject(JSObject *obj);
class ExecutionScope { class ExecutionScope {
const JSScript *script; const JSScript *script;
void startExecution(); void startExecution();
void endExecution(); void endExecution();
public: public:
explicit ExecutionScope(const JSScript *script) : script(script) { startExecution(); } explicit ExecutionScope(JSScript *script);
~ExecutionScope() { endExecution(); } ~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 inline void
DTrace::enterJSFun(JSContext *cx, JSStackFrame *fp, const JSFunction *fun, DTrace::enterJSFun(JSContext *cx, JSStackFrame *fp, JSFunction *fun, JSStackFrame *dfp,
JSStackFrame *dfp, jsuint argc, jsval *argv, jsval *lval) jsuint argc, jsval *argv, jsval *lval)
{ {
#ifdef INCLUDE_MOZILLA_DTRACE #ifdef INCLUDE_MOZILLA_DTRACE
if (!lval || VALUE_IS_FUNCTION(cx, *lval)) { if (!lval || VALUE_IS_FUNCTION(cx, *lval)) {
if (JAVASCRIPT_FUNCTION_ENTRY_ENABLED()) if (JAVASCRIPT_FUNCTION_ENTRY_ENABLED())
jsdtrace_function_entry(cx, fp, fun); enterJSFunImpl(cx, fp, fun);
if (JAVASCRIPT_FUNCTION_INFO_ENABLED()) if (JAVASCRIPT_FUNCTION_INFO_ENABLED())
jsdtrace_function_info(cx, fp, dfp, fun); handleFunctionInfo(cx, fp, dfp, fun);
if (JAVASCRIPT_FUNCTION_ARGS_ENABLED()) if (JAVASCRIPT_FUNCTION_ARGS_ENABLED())
jsdtrace_function_args(cx, fp, fun, argc, argv); handleFunctionArgs(cx, fp, fun, argc, argv);
} }
#endif #endif
} }
inline void inline void
DTrace::exitJSFun(JSContext *cx, JSStackFrame *fp, const JSFunction *fun, DTrace::exitJSFun(JSContext *cx, JSStackFrame *fp, JSFunction *fun, jsval rval, jsval *lval)
jsval rval, jsval *lval)
{ {
#ifdef INCLUDE_MOZILLA_DTRACE #ifdef INCLUDE_MOZILLA_DTRACE
if (!lval || VALUE_IS_FUNCTION(cx, *lval)) { if (!lval || VALUE_IS_FUNCTION(cx, *lval)) {
if (JAVASCRIPT_FUNCTION_RVAL_ENABLED()) if (JAVASCRIPT_FUNCTION_RVAL_ENABLED())
jsdtrace_function_rval(cx, fp, fun, rval); handleFunctionRval(cx, fp, fun, rval);
if (JAVASCRIPT_FUNCTION_RETURN_ENABLED()) if (JAVASCRIPT_FUNCTION_RETURN_ENABLED())
jsdtrace_function_return(cx, fp, fun); handleFunctionReturn(cx, fp, fun);
} }
#endif #endif
} }
inline void inline void
DTrace::finalizeObject(const JSObject *obj) DTrace::finalizeObject(JSObject *obj)
{ {
#ifdef INCLUDE_MOZILLA_DTRACE #ifdef INCLUDE_MOZILLA_DTRACE
if (JAVASCRIPT_OBJECT_FINALIZE_ENABLED()) if (JAVASCRIPT_OBJECT_FINALIZE_ENABLED())
jsdtrace_object_finalize(obj); finalizeObjectImpl(obj);
#endif #endif
} }
inline void /* Execution scope. */
DTrace::ExecutionScope::startExecution()
inline
DTrace::ExecutionScope::ExecutionScope(JSScript *script)
: script(script)
{ {
#ifdef INCLUDE_MOZILLA_DTRACE #ifdef INCLUDE_MOZILLA_DTRACE
if (JAVASCRIPT_EXECUTE_START_ENABLED()) 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 #endif
} }
inline void inline void
DTrace::ExecutionScope::endExecution() DTrace::ObjectCreationScope::handleCreation(JSObject *obj)
{ {
#ifdef INCLUDE_MOZILLA_DTRACE #ifdef INCLUDE_MOZILLA_DTRACE
if (JAVASCRIPT_EXECUTE_DONE_ENABLED()) if (JAVASCRIPT_OBJECT_CREATE_ENABLED())
jsdtrace_execute_done(script); handleCreationImpl(obj);
#endif
}
inline
DTrace::ObjectCreationScope::~ObjectCreationScope()
{
#ifdef INCLUDE_MOZILLA_DTRACE
if (JAVASCRIPT_OBJECT_CREATE_DONE_ENABLED())
handleCreationEnd();
#endif #endif
} }

Просмотреть файл

@ -1882,7 +1882,7 @@ EmitEnterBlock(JSContext *cx, JSParseNode *pn, JSCodeGenerator *cg)
} }
blockObj->scope()->freeslot = JSSLOT_FREE(&js_BlockClass); 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) EmitSpecialPropOp(JSContext *cx, JSParseNode *pn, JSOp op, JSCodeGenerator *cg)
{ {
/* /*
* Special case for obj.__proto__ and obj.__parent__ to deoptimize away * Special case for obj.__proto__ to deoptimize away from fast paths in the
* from fast paths in the interpreter and trace recorder, which skip dense * interpreter and trace recorder, which skip dense array instances by
* array instances by going up to Array.prototype before looking up the * going up to Array.prototype before looking up the property name.
* property name.
*/ */
JSAtomListElement *ale = cg->atomList.add(cg->parser, pn->pn_atom); JSAtomListElement *ale = cg->atomList.add(cg->parser, pn->pn_atom);
if (!ale) if (!ale)
@ -2713,10 +2712,9 @@ EmitPropOp(JSContext *cx, JSParseNode *pn, JSOp op, JSCodeGenerator *cg,
JS_ASSERT(pn->pn_arity == PN_NAME); JS_ASSERT(pn->pn_arity == PN_NAME);
pn2 = pn->maybeExpr(); pn2 = pn->maybeExpr();
/* Special case deoptimization on __proto__ and __parent__. */ /* Special case deoptimization for __proto__. */
if ((op == JSOP_GETPROP || op == JSOP_CALLPROP) && if ((op == JSOP_GETPROP || op == JSOP_CALLPROP) &&
(pn->pn_atom == cx->runtime->atomState.protoAtom || pn->pn_atom == cx->runtime->atomState.protoAtom) {
pn->pn_atom == cx->runtime->atomState.parentAtom)) {
if (pn2 && !js_EmitTree(cx, cg, pn2)) if (pn2 && !js_EmitTree(cx, cg, pn2))
return JS_FALSE; return JS_FALSE;
return EmitSpecialPropOp(cx, pn, callContext ? JSOP_CALLELEM : JSOP_GETELEM, cg); 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; return JS_FALSE;
} }
/* /* Special case deoptimization on __proto__, as above. */
* Special case deoptimization on __proto__ and __parent__, as if (pndot->pn_arity == PN_NAME && pndot->pn_atom == cx->runtime->atomState.protoAtom) {
* above.
*/
if (pndot->pn_arity == PN_NAME &&
(pndot->pn_atom == cx->runtime->atomState.protoAtom ||
pndot->pn_atom == cx->runtime->atomState.parentAtom)) {
if (!EmitSpecialPropOp(cx, pndot, JSOP_GETELEM, cg)) if (!EmitSpecialPropOp(cx, pndot, JSOP_GETELEM, cg))
return JS_FALSE; return JS_FALSE;
} else if (!EmitAtomOp(cx, pndot, PN_OP(pndot), cg)) { } 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 * In such cases, naively following ECMA leads to wrongful sharing of RegExp
* objects, which makes for collisions on the lastIndex property (especially * objects, which makes for collisions on the lastIndex property (especially
* for global regexps) and on any ad-hoc properties. Also, __proto__ and * for global regexps) and on any ad-hoc properties. Also, __proto__ refers to
* __parent__ refer to the pre-compilation prototype and global objects, a * the pre-compilation prototype, a pigeon-hole problem for instanceof tests.
* pigeon-hole problem for instanceof tests.
*/ */
uintN uintN
JSCGObjectList::index(JSObjectBox *objbox) 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 * args_delete to clear the corresponding reserved slot so the GC can
* collect its value. * collect its value.
*/ */
jsid id; JS_ASSERT_IF(JSVAL_IS_STRING(idval), JSVAL_TO_STRING(idval)->isAtomized());
if (!JS_ValueToId(cx, idval, &id)) jsid id = (jsid)idval;
return false;
AutoValueRooter tvr(cx); AutoValueRooter tvr(cx);
return js_DeleteProperty(cx, obj, id, tvr.addr()) && return js_DeleteProperty(cx, obj, id, tvr.addr()) &&
@ -1151,7 +1150,6 @@ call_resolve(JSContext *cx, JSObject *obj, jsval idval, uintN flags,
{ {
jsval callee; jsval callee;
JSFunction *fun; JSFunction *fun;
jsid id;
JSLocalKind localKind; JSLocalKind localKind;
JSPropertyOp getter, setter; JSPropertyOp getter, setter;
uintN slot, attrs; uintN slot, attrs;
@ -1162,14 +1160,14 @@ call_resolve(JSContext *cx, JSObject *obj, jsval idval, uintN flags,
if (!JSVAL_IS_STRING(idval)) if (!JSVAL_IS_STRING(idval))
return JS_TRUE; return JS_TRUE;
JS_ASSERT(JSVAL_TO_STRING(idval)->isAtomized());
jsid id = (jsval)idval;
callee = obj->getSlot(JSSLOT_CALLEE); callee = obj->getSlot(JSSLOT_CALLEE);
if (JSVAL_IS_VOID(callee)) if (JSVAL_IS_VOID(callee))
return JS_TRUE; return JS_TRUE;
fun = GET_FUNCTION_PRIVATE(cx, JSVAL_TO_OBJECT(callee)); 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 * Check whether the id refers to a formal parameter, local variable or
* the arguments special name. * the arguments special name.

Просмотреть файл

@ -1559,6 +1559,8 @@ js_TraceOpcode(JSContext *cx)
(n == -ndefs) ? " output:" : ",", (n == -ndefs) ? " output:" : ",",
bytes); bytes);
cx->free(bytes); cx->free(bytes);
} else {
JS_ClearPendingException(cx);
} }
} }
fprintf(tracefp, " @ %u\n", (uintN) (regs->sp - StackBase(fp))); fprintf(tracefp, " @ %u\n", (uintN) (regs->sp - StackBase(fp)));
@ -1566,10 +1568,12 @@ js_TraceOpcode(JSContext *cx)
fprintf(tracefp, " stack: "); fprintf(tracefp, " stack: ");
for (siter = StackBase(fp); siter < regs->sp; siter++) { for (siter = StackBase(fp); siter < regs->sp; siter++) {
str = js_ValueToString(cx, *siter); str = js_ValueToString(cx, *siter);
if (!str) if (!str) {
fputs("<null>", tracefp); fputs("<null>", tracefp);
else } else {
JS_ClearPendingException(cx);
js_FileEscapedString(tracefp, str, 0); js_FileEscapedString(tracefp, str, 0);
}
fputc(' ', tracefp); fputc(' ', tracefp);
} }
fputc('\n', tracefp); fputc('\n', tracefp);
@ -1591,6 +1595,8 @@ js_TraceOpcode(JSContext *cx)
(n == -nuses) ? " inputs:" : ",", (n == -nuses) ? " inputs:" : ",",
bytes); bytes);
cx->free(bytes); cx->free(bytes);
} else {
JS_ClearPendingException(cx);
} }
} }
fprintf(tracefp, " @ %u\n", (uintN) (regs->sp - StackBase(fp))); fprintf(tracefp, " @ %u\n", (uintN) (regs->sp - StackBase(fp)));

Просмотреть файл

@ -126,59 +126,29 @@ JSClass js_ObjectClass = {
#if JS_HAS_OBJ_PROTO_PROP #if JS_HAS_OBJ_PROTO_PROP
static JSBool static JSBool
obj_getSlot(JSContext *cx, JSObject *obj, jsval id, jsval *vp); obj_getProto(JSContext *cx, JSObject *obj, jsid id, jsval *vp);
static JSBool 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[] = { 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_getProto, obj_setProto},
{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},
{0,0,0,0,0} {0,0,0,0,0}
}; };
/* NB: JSSLOT_PROTO and JSSLOT_PARENT are already indexes into object_props. */
#define JSSLOT_COUNT 2
static JSBool static JSBool
ReportStrictSlot(JSContext *cx, uint32 slot) obj_getProto(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
{ {
if (slot == JSSLOT_PROTO) JS_ASSERT(id == INT_TO_JSID(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;
}
/* Let obj->checkAccess get the slot's value, based on the access mode. */ /* 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; return JS_FALSE;
pobj = JSVAL_TO_OBJECT(*vp); if (JSObject *pobj = JSVAL_TO_OBJECT(*vp)) {
if (pobj) { JSClass *clasp = pobj->getClass();
clasp = pobj->getClass();
if (clasp == &js_CallClass || clasp == &js_BlockClass) { if (clasp == &js_CallClass || clasp == &js_BlockClass) {
/* Censor activations and lexical scopes per ECMA-262. */ /* Censor activations and lexical scopes per ECMA-262. */
*vp = JSVAL_NULL; *vp = JSVAL_NULL;
@ -188,8 +158,8 @@ obj_getSlot(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
* censor. So it cannot escape to scripts. * censor. So it cannot escape to scripts.
*/ */
JS_ASSERT(clasp != &js_DeclEnvClass); JS_ASSERT(clasp != &js_DeclEnvClass);
if (pobj->map->ops->thisObject) { if (JSObjectOp thisObject = pobj->map->ops->thisObject) {
pobj = pobj->map->ops->thisObject(cx, pobj); pobj = thisObject(cx, pobj);
if (!pobj) if (!pobj)
return JS_FALSE; return JS_FALSE;
*vp = OBJECT_TO_JSVAL(pobj); *vp = OBJECT_TO_JSVAL(pobj);
@ -200,17 +170,14 @@ obj_getSlot(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
} }
static JSBool static JSBool
obj_setSlot(JSContext *cx, JSObject *obj, jsval id, jsval *vp) obj_setProto(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
{ {
JSObject *pobj; JS_ASSERT(id == INT_TO_JSID(JSSLOT_PROTO));
uint32 slot;
jsid propid;
uintN attrs;
if (!JSVAL_IS_OBJECT(*vp)) if (!JSVAL_IS_OBJECT(*vp))
return JS_TRUE; return JS_TRUE;
pobj = JSVAL_TO_OBJECT(*vp);
JSObject *pobj = JSVAL_TO_OBJECT(*vp);
if (pobj) { if (pobj) {
/* /*
* Innerize pobj here to avoid sticking unwanted properties on the * 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) if (!pobj)
return JS_FALSE; 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; return JS_FALSE;
/* __parent__ is readonly and permanent, only __proto__ may be set. */ return js_SetProtoOrParent(cx, obj, JSSLOT_PROTO, pobj, JS_TRUE);
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);
} }
#else /* !JS_HAS_OBJ_PROTO_PROP */ #else /* !JS_HAS_OBJ_PROTO_PROP */
@ -300,15 +264,8 @@ js_SetProtoOrParent(JSContext *cx, JSObject *obj, uint32 slot, JSObject *pobj,
} }
if (ssr.cycle) { if (ssr.cycle) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CYCLIC_VALUE,
JSMSG_CYCLIC_VALUE, (slot == JSSLOT_PROTO) ? js_proto_str : "parent");
#if JS_HAS_OBJ_PROTO_PROP
object_props[slot].name
#else
(slot == JSSLOT_PROTO) ? js_proto_str
: js_parent_str
#endif
);
return JS_FALSE; return JS_FALSE;
} }
} }
@ -1951,13 +1908,12 @@ obj_keys(JSContext *cx, uintN argc, jsval *vp)
return JS_FALSE; return JS_FALSE;
*vp = OBJECT_TO_JSVAL(aobj); *vp = OBJECT_TO_JSVAL(aobj);
jsval *slots = aobj->dslots;
size_t len = ida.length(); size_t len = ida.length();
JS_ASSERT(aobj->getDenseArrayCapacity() >= len); JS_ASSERT(aobj->getDenseArrayCapacity() >= len);
for (size_t i = 0; i < len; i++) { for (size_t i = 0; i < len; i++) {
jsid id = ida[i]; jsid id = ida[i];
if (JSID_IS_INT(id)) { 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; return JS_FALSE;
} else { } 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 * to by a QName, actually appears as a string jsid -- but in the
* interests of fidelity we pass object jsids through unchanged. * 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) { if (normalUnwind && count > 1) {
--count; --count;
JS_LOCK_OBJ(cx, obj); 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; normalUnwind = JS_FALSE;
else else
memcpy(obj->dslots, fp->slots + depth + 1, count * sizeof(jsval)); memcpy(obj->dslots, fp->slots + depth + 1, count * sizeof(jsval));
@ -3521,35 +3477,28 @@ bad:
goto out; 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 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); JS_ASSERT(nslots > JS_INITIAL_NSLOTS);
jsval* slots; size_t nwords = slotsToDynamicWords(nslots);
slots = (jsval*) cx->malloc(SLOTS_TO_DYNAMIC_WORDS(nslots) * sizeof(jsval)); dslots = (jsval*) cx->malloc(nwords * sizeof(jsval));
if (!slots) if (!dslots)
return false; return false;
*slots++ = nslots; dslots++;
dslots[-1] = nslots;
/* clear the newly allocated cells. */ /* clear the newly allocated cells. */
for (jsuint n = JS_INITIAL_NSLOTS; n < nslots; ++n) for (jsuint i = JS_INITIAL_NSLOTS; i < nslots; i++)
slots[n - JS_INITIAL_NSLOTS] = JSVAL_VOID; dslots[i - JS_INITIAL_NSLOTS] = JSVAL_VOID;
obj->dslots = slots;
return true; return true;
} }
bool bool
js_GrowSlots(JSContext *cx, JSObject *obj, size_t nslots) JSObject::growSlots(JSContext *cx, size_t nslots)
{ {
/* /*
* Minimal number of dynamic slots to allocate. * 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) if (nslots <= JS_INITIAL_NSLOTS)
return JS_TRUE; 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 * 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 { } else {
nwords = JS_ROUNDUP(nwords, LINEAR_GROWTH_STEP); 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 * If nothing was allocated yet, treat it as initial allocation (but with
* the exponential growth algorithm applied). * the exponential growth algorithm applied).
*/ */
jsval* slots = obj->dslots; if (!dslots)
if (!slots) return allocSlots(cx, nslots);
return js_AllocSlots(cx, obj, nslots);
size_t oslots = size_t(slots[-1]); size_t oldnslots = size_t(dslots[-1]);
slots = (jsval*) cx->realloc(slots - 1, nwords * sizeof(jsval)); jsval *tmpdslots = (jsval*) cx->realloc(dslots - 1, nwords * sizeof(jsval));
if (!slots) if (!tmpdslots)
return false; return false; /* Leave dslots at its old size. */
dslots = tmpdslots;
*slots++ = nslots; dslots++;
obj->dslots = slots; dslots[-1] = nslots;
/* Initialize the additional slots we added. */ /* Initialize the additional slots we added. */
JS_ASSERT(nslots > oslots); JS_ASSERT(nslots > oldnslots);
for (size_t i = oslots; i < nslots; i++) for (size_t i = oldnslots; i < nslots; i++)
slots[i - JS_INITIAL_NSLOTS] = JSVAL_VOID; dslots[i - JS_INITIAL_NSLOTS] = JSVAL_VOID;
return true; return true;
} }
void void
js_ShrinkSlots(JSContext *cx, JSObject *obj, size_t nslots) JSObject::shrinkSlots(JSContext *cx, size_t nslots)
{ {
jsval* slots = obj->dslots;
/* Nothing to shrink? */ /* Nothing to shrink? */
if (!slots) if (!dslots)
return; return;
JS_ASSERT(size_t(slots[-1]) > JS_INITIAL_NSLOTS); JS_ASSERT(size_t(dslots[-1]) > JS_INITIAL_NSLOTS);
JS_ASSERT(nslots <= size_t(slots[-1])); JS_ASSERT(nslots <= size_t(dslots[-1]));
if (nslots <= JS_INITIAL_NSLOTS) { if (nslots <= JS_INITIAL_NSLOTS) {
obj->freeSlotsArray(cx); freeSlotsArray(cx);
obj->dslots = NULL; dslots = NULL;
} else { } else {
size_t nwords = SLOTS_TO_DYNAMIC_WORDS(nslots); size_t nwords = slotsToDynamicWords(nslots);
slots = (jsval*) cx->realloc(slots - 1, nwords * sizeof(jsval)); jsval *tmpdslots = (jsval*) cx->realloc(dslots - 1, nwords * sizeof(jsval));
if (!slots) if (!tmpdslots)
return; /* Leave obj->dslots at its old size. */ return; /* Leave dslots at its old size. */
*slots++ = nslots; dslots = tmpdslots;
obj->dslots = slots;
dslots++;
dslots[-1] = nslots;
} }
} }
@ -3637,10 +3586,9 @@ bool
js_EnsureReservedSlots(JSContext *cx, JSObject *obj, size_t nreserved) js_EnsureReservedSlots(JSContext *cx, JSObject *obj, size_t nreserved)
{ {
JS_ASSERT(obj->isNative()); JS_ASSERT(obj->isNative());
JS_ASSERT(!obj->dslots);
uintN nslots = JSSLOT_FREE(obj->getClass()) + nreserved; 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; return false;
JSScope *scope = obj->scope(); JSScope *scope = obj->scope();
@ -3839,8 +3787,8 @@ js_ConstructObject(JSContext *cx, JSClass *clasp, JSObject *proto,
AutoValueRooter tvr(cx, cval); AutoValueRooter tvr(cx, cval);
/* /*
* If proto or parent are NULL, set them to Constructor.prototype and/or * If proto is NULL, set it to Constructor.prototype, just like JSOP_NEW
* Constructor.__parent__, just like JSOP_NEW does. * does, likewise for the new object's parent.
*/ */
ctor = JSVAL_TO_OBJECT(cval); ctor = JSVAL_TO_OBJECT(cval);
if (!parent) if (!parent)
@ -3900,7 +3848,7 @@ js_AllocSlot(JSContext *cx, JSObject *obj, uint32 *slotp)
} }
if (scope->freeslot >= obj->numSlots() && if (scope->freeslot >= obj->numSlots() &&
!js_GrowSlots(cx, obj, scope->freeslot + 1)) { !obj->growSlots(cx, scope->freeslot + 1)) {
return JS_FALSE; 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 * 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 * need that hook only for certain classes used when precompiling scripts
* and functions ("brutal sharing"). But for general safety of built-in * and functions ("brutal sharing"). But for general safety of built-in
* magic properties such as __proto__ and __parent__, we route all access * magic properties like __proto__, we route all access checks, even for
* checks, even for classes that stub out checkAccess, through the global * classes that stub out checkAccess, through the global checkObjectAccess
* checkObjectAccess hook. This covers precompilation-based sharing and * hook. This covers precompilation-based sharing and (possibly
* (possibly unintended) runtime sharing across trust boundaries. * unintended) runtime sharing across trust boundaries.
*/ */
clasp = pobj->getClass(); clasp = pobj->getClass();
check = clasp->checkAccess; check = clasp->checkAccess;
@ -6304,7 +6252,7 @@ js_TraceObject(JSTracer *trc, JSObject *obj)
*/ */
size_t slots = scope->freeslot; size_t slots = scope->freeslot;
if (obj->numSlots() != slots) if (obj->numSlots() != slots)
js_ShrinkSlots(cx, obj, slots); obj->shrinkSlots(cx, slots);
} }
#ifdef JS_DUMP_SCOPE_METERS #ifdef JS_DUMP_SCOPE_METERS
@ -6432,17 +6380,17 @@ js_SetReservedSlot(JSContext *cx, JSObject *obj, uint32 index, jsval v)
#endif #endif
uint32 slot = JSSLOT_START(clasp) + index; 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 * 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). * be accurate for obj (see comment below).
*/ */
uint32 nslots = JSSLOT_FREE(clasp); uint32 nslots = JSSLOT_FREE(clasp);
if (clasp->reserveSlots) if (clasp->reserveSlots)
nslots += clasp->reserveSlots(cx, obj); nslots += clasp->reserveSlots(cx, obj);
JS_ASSERT(slot < nslots); JS_ASSERT(slot < nslots);
if (!js_AllocSlots(cx, obj, nslots)) { if (!obj->allocSlots(cx, nslots)) {
JS_UNLOCK_OBJ(cx, obj); JS_UNLOCK_OBJ(cx, obj);
return false; return false;
} }

Просмотреть файл

@ -296,6 +296,22 @@ struct JSObject {
return dslots ? (uint32)dslots[-1] : (uint32)JS_INITIAL_NSLOTS; 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) { jsval& getSlotRef(uintN slot) {
return (slot < JS_INITIAL_NSLOTS) return (slot < JS_INITIAL_NSLOTS)
? fslots[slot] ? fslots[slot]
@ -364,7 +380,7 @@ struct JSObject {
JSObject *parent = getParent(); JSObject *parent = getParent();
if (parent) if (parent)
JS_CALL_OBJECT_TRACER(trc, parent, "__parent__"); JS_CALL_OBJECT_TRACER(trc, parent, "parent");
} }
JSObject *getGlobal(); JSObject *getGlobal();
@ -417,8 +433,6 @@ struct JSObject {
// The static assertion isn't inline because that doesn't work on Mac.) // The static assertion isn't inline because that doesn't work on Mac.)
inline void staticAssertArrayLengthIsInPrivateSlot(); inline void staticAssertArrayLengthIsInPrivateSlot();
inline bool isDenseArrayMinLenCapOk() const;
inline uint32 uncheckedGetArrayLength() const; inline uint32 uncheckedGetArrayLength() const;
inline uint32 uncheckedGetDenseArrayCapacity() const; inline uint32 uncheckedGetDenseArrayCapacity() const;
@ -435,7 +449,10 @@ struct JSObject {
inline uint32 getDenseArrayCapacity() const; inline uint32 getDenseArrayCapacity() const;
inline void setDenseArrayCapacity(uint32 capacity); // XXX: bug 558263 will remove this 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 getDenseArrayElement(uint32 i) const;
inline jsval *addressOfDenseArrayElement(uint32 i);
inline void setDenseArrayElement(uint32 i, jsval v); inline void setDenseArrayElement(uint32 i, jsval v);
inline jsval *getDenseArrayElements() const; // returns pointer to the Array's elements array 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 extern void
js_FreeSlot(JSContext *cx, JSObject *obj, uint32 slot); 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 * 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 * slots. The function can be called only for native objects just created with

Просмотреть файл

@ -46,10 +46,7 @@
#include "jsiter.h" #include "jsiter.h"
#include "jsobj.h" #include "jsobj.h"
#include "jsscope.h" #include "jsscope.h"
#ifdef INCLUDE_MOZILLA_DTRACE
#include "jsdtracef.h" #include "jsdtracef.h"
#endif
#include "jsscopeinlines.h" #include "jsscopeinlines.h"
@ -110,18 +107,26 @@ JSObject::setPrimitiveThis(jsval pthis)
fslots[JSSLOT_PRIMITIVE_THIS] = pthis; fslots[JSSLOT_PRIMITIVE_THIS] = pthis;
} }
inline void JSObject::staticAssertArrayLengthIsInPrivateSlot() inline void
JSObject::staticAssertArrayLengthIsInPrivateSlot()
{ {
JS_STATIC_ASSERT(JSSLOT_ARRAY_LENGTH == JSSLOT_PRIVATE); JS_STATIC_ASSERT(JSSLOT_ARRAY_LENGTH == JSSLOT_PRIVATE);
} }
inline bool JSObject::isDenseArrayMinLenCapOk() const inline bool
JSObject::isDenseArrayMinLenCapOk(bool strictAboutLength) const
{ {
JS_ASSERT(isDenseArray()); JS_ASSERT(isDenseArray());
uint32 length = uncheckedGetArrayLength(); uint32 length = uncheckedGetArrayLength();
uint32 capacity = uncheckedGetDenseArrayCapacity(); uint32 capacity = uncheckedGetDenseArrayCapacity();
uint32 minLenCap = uint32(fslots[JSSLOT_DENSE_ARRAY_MINLENCAP]); 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 inline uint32
@ -192,7 +197,7 @@ inline uint32
JSObject::getDenseArrayCapacity() const JSObject::getDenseArrayCapacity() const
{ {
JS_ASSERT(isDenseArray()); JS_ASSERT(isDenseArray());
JS_ASSERT(isDenseArrayMinLenCapOk()); JS_ASSERT(isDenseArrayMinLenCapOk(/* strictAboutLength = */false));
return uncheckedGetDenseArrayCapacity(); return uncheckedGetDenseArrayCapacity();
} }
@ -214,6 +219,14 @@ JSObject::getDenseArrayElement(uint32 i) const
return dslots[i]; return dslots[i];
} }
inline jsval *
JSObject::addressOfDenseArrayElement(uint32 i)
{
JS_ASSERT(isDenseArray());
JS_ASSERT(i < getDenseArrayCapacity());
return &dslots[i];
}
inline void inline void
JSObject::setDenseArrayElement(uint32 i, jsval v) 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. */ /* Let JSScope::create set freeslot so as to reserve slots. */
JS_ASSERT(scope->freeslot >= JSSLOT_PRIVATE); JS_ASSERT(scope->freeslot >= JSSLOT_PRIVATE);
if (scope->freeslot > JS_INITIAL_NSLOTS && if (scope->freeslot > JS_INITIAL_NSLOTS &&
!js_AllocSlots(cx, obj, scope->freeslot)) { !obj->allocSlots(cx, scope->freeslot)) {
scope->destroy(cx); scope->destroy(cx);
goto bad; goto bad;
} }
@ -496,10 +509,7 @@ static inline JSObject *
NewObjectWithGivenProto(JSContext *cx, JSClass *clasp, JSObject *proto, NewObjectWithGivenProto(JSContext *cx, JSClass *clasp, JSObject *proto,
JSObject *parent, size_t objectSize = 0) JSObject *parent, size_t objectSize = 0)
{ {
#ifdef INCLUDE_MOZILLA_DTRACE DTrace::ObjectCreationScope objectCreationScope(cx, cx->fp, clasp);
if (JAVASCRIPT_OBJECT_CREATE_START_ENABLED())
jsdtrace_object_create_start(cx->fp, clasp);
#endif
/* Assert that the class is a proper class. */ /* Assert that the class is a proper class. */
JS_ASSERT_IF(clasp->flags & JSCLASS_IS_EXTENDED, JS_ASSERT_IF(clasp->flags & JSCLASS_IS_EXTENDED,
@ -565,12 +575,7 @@ NewObjectWithGivenProto(JSContext *cx, JSClass *clasp, JSObject *proto,
} }
out: out:
#ifdef INCLUDE_MOZILLA_DTRACE objectCreationScope.handleCreation(obj);
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
return obj; return obj;
} }

Просмотреть файл

@ -3274,6 +3274,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
cond -= tail; cond -= tail;
DECOMPILE_CODE(pc + oplen, cond - oplen); DECOMPILE_CODE(pc + oplen, cond - oplen);
pc += cond; pc += cond;
oplen = js_CodeSpec[*pc].length;
elseif = JS_TRUE; elseif = JS_TRUE;
goto if_again; goto if_again;
} }

Просмотреть файл

@ -3333,9 +3333,8 @@ BEGIN_CASE(JSOP_INITMETHOD)
* So check first. * So check first.
* *
* On a hit, if the cached sprop has a non-default setter, it must be * On a hit, if the cached sprop has a non-default setter, it must be
* __proto__ or __parent__. If sprop->parent != scope->lastProperty(), * __proto__. If sprop->parent != scope->lastProperty(), there is a
* there is a repeated property name. The fast path does not handle these * repeated property name. The fast path does not handle these two cases.
* two cases.
*/ */
if (CX_OWNS_OBJECT_TITLE(cx, obj) && if (CX_OWNS_OBJECT_TITLE(cx, obj) &&
JS_PROPERTY_CACHE(cx).testForInit(rt, regs.pc, obj, scope, &sprop, &entry) && 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; uintN slot = JSSLOT_FREE(&js_BlockClass) + n;
if (slot >= blockObj->numSlots() && if (slot >= blockObj->numSlots() &&
!js_GrowSlots(cx, blockObj, slot + 1)) { !blockObj->growSlots(cx, slot + 1)) {
return JS_FALSE; return JS_FALSE;
} }
blockObj->scope()->freeslot = slot + 1; blockObj->scope()->freeslot = slot + 1;
@ -6274,6 +6274,7 @@ Parser::unaryExpr()
break; break;
case TOK_DELETE: case TOK_DELETE:
{
pn = UnaryNode::create(tc); pn = UnaryNode::create(tc);
if (!pn) if (!pn)
return NULL; return NULL;
@ -6301,12 +6302,14 @@ Parser::unaryExpr()
JSMSG_DEPRECATED_DELETE_OPERAND)) JSMSG_DEPRECATED_DELETE_OPERAND))
return NULL; return NULL;
pn2->pn_op = JSOP_DELNAME; pn2->pn_op = JSOP_DELNAME;
if (pn2->pn_atom == context->runtime->atomState.argumentsAtom)
tc->flags |= TCF_FUN_HEAVYWEIGHT;
break; break;
default:; default:;
} }
pn->pn_kid = pn2; pn->pn_kid = pn2;
break; break;
}
case TOK_ERROR: case TOK_ERROR:
return NULL; return NULL;

Просмотреть файл

@ -55,7 +55,7 @@ class RecursiveSlotMap : public SlotMap
{ {
/* Check if the return value should be promoted. */ /* Check if the return value should be promoted. */
if (slots[downPostSlots].lastCheck == TypeCheck_Demote) 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. */ /* Adjust any global variables. */
for (unsigned i = downPostSlots + 1; i < slots.length(); i++) for (unsigned i = downPostSlots + 1; i < slots.length(); i++)
adjustType(slots[i]); adjustType(slots[i]);
@ -111,10 +111,10 @@ class UpRecursiveSlotMap : public RecursiveSlotMap
*/ */
lir->insStore(rval_ins, lirbuf->sp, -mRecorder.tree->nativeStackBase, ACC_STACK); 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->insImmWord(-int(downPostSlots) * sizeof(double)));
lir->insStore(lirbuf->sp, lirbuf->state, offsetof(TracerState, sp), ACC_OTHER); 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->insImmWord(-int(sizeof(FrameInfo*))));
lir->insStore(lirbuf->rp, lirbuf->state, offsetof(TracerState, rp), ACC_OTHER); lir->insStore(lirbuf->rp, lirbuf->state, offsetof(TracerState, rp), ACC_OTHER);
} }
@ -286,8 +286,8 @@ TraceRecorder::upRecursion()
/* Guard that rp >= sr + 1 */ /* Guard that rp >= sr + 1 */
guard(true, guard(true,
lir->ins2(LIR_pge, lirbuf->rp, lir->ins2(LIR_gep, lirbuf->rp,
lir->ins2(LIR_piadd, lir->ins2(LIR_addp,
lir->insLoad(LIR_ldp, lirbuf->state, lir->insLoad(LIR_ldp, lirbuf->state,
offsetof(TracerState, sor), ACC_OTHER), offsetof(TracerState, sor), ACC_OTHER),
INS_CONSTWORD(sizeof(FrameInfo*)))), INS_CONSTWORD(sizeof(FrameInfo*)))),
@ -299,7 +299,7 @@ TraceRecorder::upRecursion()
/* Guard that the FrameInfo above is the same FrameInfo pointer. */ /* Guard that the FrameInfo above is the same FrameInfo pointer. */
VMSideExit* exit = snapshot(RECURSIVE_MISMATCH_EXIT); VMSideExit* exit = snapshot(RECURSIVE_MISMATCH_EXIT);
LIns* prev_rp = lir->insLoad(LIR_ldp, lirbuf->rp, -int32_t(sizeof(FrameInfo*)), ACC_RSTACK); 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 * 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. * end-of-recursion and recursion-returns-to-different-pc.
*/ */
guard(true, guard(true,
lir->ins2(LIR_peq, lir->ins2(LIR_eqp,
addName(lir->insLoad(LIR_ldp, fp_ins, addName(lir->insLoad(LIR_ldp, fp_ins,
offsetof(JSStackFrame, script), ACC_OTHER), offsetof(JSStackFrame, script), ACC_OTHER),
"script"), "script"),
@ -429,7 +429,7 @@ TraceRecorder::slurpDownFrames(jsbytecode* return_pc)
/* fp->down->regs->pc should be == pc. */ /* fp->down->regs->pc should be == pc. */
guard(true, guard(true,
lir->ins2(LIR_peq, lir->ins2(LIR_eqp,
lir->insLoad(LIR_ldp, lir->insLoad(LIR_ldp,
addName(lir->insLoad(LIR_ldp, fp_ins, addName(lir->insLoad(LIR_ldp, fp_ins,
offsetof(JSStackFrame, regs), ACC_OTHER), offsetof(JSStackFrame, regs), ACC_OTHER),
@ -440,8 +440,8 @@ TraceRecorder::slurpDownFrames(jsbytecode* return_pc)
/* fp->down->argc should be == argc. */ /* fp->down->argc should be == argc. */
guard(true, guard(true,
lir->ins2(LIR_eq, lir->ins2(LIR_eqi,
addName(lir->insLoad(LIR_ld, fp_ins, offsetof(JSStackFrame, argc), addName(lir->insLoad(LIR_ldi, fp_ins, offsetof(JSStackFrame, argc),
ACC_OTHER), ACC_OTHER),
"argc"), "argc"),
INS_CONST(cx->fp->argc)), INS_CONST(cx->fp->argc)),
@ -550,10 +550,10 @@ TraceRecorder::slurpDownFrames(jsbytecode* return_pc)
case TT_SPECIAL: case TT_SPECIAL:
case TT_VOID: case TT_VOID:
case TT_INT32: 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; break;
case TT_DOUBLE: 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; break;
case TT_FUNCTION: case TT_FUNCTION:
case TT_OBJECT: case TT_OBJECT:
@ -609,7 +609,7 @@ TraceRecorder::slurpDownFrames(jsbytecode* return_pc)
/* stack vals */ /* stack vals */
unsigned nfixed = fp->script->nfixed; unsigned nfixed = fp->script->nfixed;
jsval* stack = StackBase(fp); jsval* stack = StackBase(fp);
LIns* stack_ins = addName(lir->ins2(LIR_piadd, LIns* stack_ins = addName(lir->ins2(LIR_addp,
slots_ins, slots_ins,
INS_CONSTWORD(nfixed * sizeof(jsval))), INS_CONSTWORD(nfixed * sizeof(jsval))),
"stackBase"); "stackBase");
@ -684,12 +684,12 @@ TraceRecorder::downRecursion()
JS_ASSERT(tree->maxNativeStackSlots >= tree->nativeStackBase / sizeof(double)); JS_ASSERT(tree->maxNativeStackSlots >= tree->nativeStackBase / sizeof(double));
int guardSlots = slots + tree->maxNativeStackSlots - int guardSlots = slots + tree->maxNativeStackSlots -
tree->nativeStackBase / sizeof(double); tree->nativeStackBase / sizeof(double);
LIns* sp_top = lir->ins2(LIR_piadd, lirbuf->sp, lir->insImmWord(guardSlots * sizeof(double))); LIns* sp_top = lir->ins2(LIR_addp, lirbuf->sp, lir->insImmWord(guardSlots * sizeof(double)));
guard(true, lir->ins2(LIR_plt, sp_top, eos_ins), OOM_EXIT); guard(true, lir->ins2(LIR_ltp, sp_top, eos_ins), OOM_EXIT);
/* Guard that there is enough call stack space. */ /* Guard that there is enough call stack space. */
LIns* rp_top = lir->ins2(LIR_piadd, lirbuf->rp, lir->insImmWord(sizeof(FrameInfo*))); LIns* rp_top = lir->ins2(LIR_addp, lirbuf->rp, lir->insImmWord(sizeof(FrameInfo*)));
guard(true, lir->ins2(LIR_plt, rp_top, eor_ins), OOM_EXIT); 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 * 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); VisitStackSlots(visitor, cx, callDepth);
/* Add space for a new JIT frame. */ /* 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); 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); lir->insStore(lirbuf->rp, lirbuf->state, offsetof(TracerState, rp), ACC_OTHER);
--callDepth; --callDepth;
clearCurrentFrameSlotsFromTracker(nativeFrameTracker); clearCurrentFrameSlotsFromTracker(nativeFrameTracker);
@ -734,19 +734,19 @@ JS_REQUIRES_STACK LIns*
TraceRecorder::slurpInt32Slot(LIns* val_ins, jsval* vp, VMSideExit* exit) TraceRecorder::slurpInt32Slot(LIns* val_ins, jsval* vp, VMSideExit* exit)
{ {
guard(true, guard(true,
lir->ins2(LIR_or, lir->ins2(LIR_ori,
lir->ins2(LIR_peq, lir->ins2(LIR_eqp,
lir->ins2(LIR_piand, val_ins, INS_CONSTWORD(JSVAL_TAGMASK)), lir->ins2(LIR_andp, val_ins, INS_CONSTWORD(JSVAL_TAGMASK)),
INS_CONSTWORD(JSVAL_DOUBLE)), INS_CONSTWORD(JSVAL_DOUBLE)),
lir->ins2(LIR_peq, lir->ins2(LIR_eqp,
lir->ins2(LIR_piand, val_ins, INS_CONSTWORD(1)), lir->ins2(LIR_andp, val_ins, INS_CONSTWORD(1)),
INS_CONSTWORD(1))), INS_CONSTWORD(1))),
exit); exit);
LIns* space = lir->insAlloc(sizeof(int32)); LIns* space = lir->insAlloc(sizeof(int32));
LIns* args[] = { space, val_ins }; LIns* args[] = { space, val_ins };
LIns* result = lir->insCall(&js_TryUnboxInt32_ci, args); LIns* result = lir->insCall(&js_TryUnboxInt32_ci, args);
guard(false, lir->insEqI_0(result), exit); 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; return int32_ins;
} }
@ -754,12 +754,12 @@ JS_REQUIRES_STACK LIns*
TraceRecorder::slurpDoubleSlot(LIns* val_ins, jsval* vp, VMSideExit* exit) TraceRecorder::slurpDoubleSlot(LIns* val_ins, jsval* vp, VMSideExit* exit)
{ {
guard(true, guard(true,
lir->ins2(LIR_or, lir->ins2(LIR_ori,
lir->ins2(LIR_peq, lir->ins2(LIR_eqp,
lir->ins2(LIR_piand, val_ins, INS_CONSTWORD(JSVAL_TAGMASK)), lir->ins2(LIR_andp, val_ins, INS_CONSTWORD(JSVAL_TAGMASK)),
INS_CONSTWORD(JSVAL_DOUBLE)), INS_CONSTWORD(JSVAL_DOUBLE)),
lir->ins2(LIR_peq, lir->ins2(LIR_eqp,
lir->ins2(LIR_piand, val_ins, INS_CONSTWORD(1)), lir->ins2(LIR_andp, val_ins, INS_CONSTWORD(1)),
INS_CONSTWORD(1))), INS_CONSTWORD(1))),
exit); exit);
LIns* args[] = { val_ins }; LIns* args[] = { val_ins };
@ -771,11 +771,11 @@ JS_REQUIRES_STACK LIns*
TraceRecorder::slurpSpecialSlot(LIns* val_ins, jsval* vp, VMSideExit* exit) TraceRecorder::slurpSpecialSlot(LIns* val_ins, jsval* vp, VMSideExit* exit)
{ {
guard(true, guard(true,
lir->ins2(LIR_peq, lir->ins2(LIR_eqp,
lir->ins2(LIR_piand, val_ins, INS_CONSTWORD(JSVAL_TAGMASK)), lir->ins2(LIR_andp, val_ins, INS_CONSTWORD(JSVAL_TAGMASK)),
INS_CONSTWORD(JSVAL_SPECIAL)), INS_CONSTWORD(JSVAL_SPECIAL)),
exit); 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); bool_ins = p2i(bool_ins);
return bool_ins; return bool_ins;
} }
@ -783,7 +783,7 @@ TraceRecorder::slurpSpecialSlot(LIns* val_ins, jsval* vp, VMSideExit* exit)
JS_REQUIRES_STACK LIns* JS_REQUIRES_STACK LIns*
TraceRecorder::slurpVoidSlot(LIns* val_ins, jsval* vp, VMSideExit* exit) 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(); return INS_VOID();
} }
@ -791,11 +791,11 @@ JS_REQUIRES_STACK LIns*
TraceRecorder::slurpStringSlot(LIns* val_ins, jsval* vp, VMSideExit* exit) TraceRecorder::slurpStringSlot(LIns* val_ins, jsval* vp, VMSideExit* exit)
{ {
guard(true, guard(true,
lir->ins2(LIR_peq, lir->ins2(LIR_eqp,
lir->ins2(LIR_piand, val_ins, INS_CONSTWORD(JSVAL_TAGMASK)), lir->ins2(LIR_andp, val_ins, INS_CONSTWORD(JSVAL_TAGMASK)),
INS_CONSTWORD(JSVAL_STRING)), INS_CONSTWORD(JSVAL_STRING)),
exit); 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; return str_ins;
} }
@ -814,13 +814,13 @@ TraceRecorder::slurpObjectSlot(LIns* val_ins, jsval* vp, VMSideExit* exit)
/* Must be an object */ /* Must be an object */
guard(true, 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); exit);
/* Must NOT have a function class */ /* Must NOT have a function class */
guard(false, guard(false,
lir->ins2(LIR_peq, lir->ins2(LIR_eqp,
lir->ins2(LIR_piand, lir->ins2(LIR_andp,
lir->insLoad(LIR_ldp, val_ins, offsetof(JSObject, classword), lir->insLoad(LIR_ldp, val_ins, offsetof(JSObject, classword),
ACC_OTHER), ACC_OTHER),
INS_CONSTWORD(~JSSLOT_CLASS_MASK_BITS)), INS_CONSTWORD(~JSSLOT_CLASS_MASK_BITS)),
@ -837,13 +837,13 @@ TraceRecorder::slurpFunctionSlot(LIns* val_ins, jsval* vp, VMSideExit* exit)
/* Must be an object */ /* Must be an object */
guard(true, 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); exit);
/* Must have a function class */ /* Must have a function class */
guard(true, guard(true,
lir->ins2(LIR_peq, lir->ins2(LIR_eqp,
lir->ins2(LIR_piand, lir->ins2(LIR_andp,
lir->insLoad(LIR_ldp, val_ins, offsetof(JSObject, classword), lir->insLoad(LIR_ldp, val_ins, offsetof(JSObject, classword),
ACC_OTHER), ACC_OTHER),
INS_CONSTWORD(~JSSLOT_CLASS_MASK_BITS)), INS_CONSTWORD(~JSSLOT_CLASS_MASK_BITS)),

Просмотреть файл

@ -2382,10 +2382,10 @@ class RegExpNativeCompiler {
LIns* compileFlatSingleChar(jschar ch, LIns* pos, LInsList& fails) 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)) if (!fails.append(to_fail))
return NULL; 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. // Extra characters that need to be compared against when doing folding.
struct extra { struct extra {
@ -2402,7 +2402,7 @@ class RegExpNativeCompiler {
if (ch != lch) { if (ch != lch) {
if (L'A' <= ch && ch <= L'Z') { if (L'A' <= ch && ch <= L'Z') {
// Fast conversion of text character to lower case by OR-ing with 32. // 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 // 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 // |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 // case. Note that the code points of the non-ASCII forms both have the
@ -2464,17 +2464,17 @@ class RegExpNativeCompiler {
gen: gen:
for (int i = 0; i < nextras; ++i) { 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); LIns *branch = lir->insBranch(LIR_jt, test, 0);
extras[i].match = branch; 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; return NULL;
for (int i = 0; i < nextras; ++i) for (int i = 0; i < nextras; ++i)
targetCurrentPoint(extras[i].match); 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) JS_INLINE bool hasCases(jschar ch)
@ -2516,22 +2516,22 @@ class RegExpNativeCompiler {
} }
LIns* to_fail = lir->insBranch(LIR_jf, LIns* to_fail = lir->insBranch(LIR_jf,
lir->ins2(LIR_plt, lir->ins2(LIR_ltp,
pos, pos,
lir->ins2(LIR_piadd, lir->ins2(LIR_addp,
cpend, cpend,
lir->insImmWord(-2))), lir->insImmWord(-2))),
0); 0);
if (!fails.append(to_fail)) if (!fails.append(to_fail))
return NULL; 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 ? 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; 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 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) LIns* compileFlat(RENode *&node, LIns* pos, LInsList& fails)
@ -2603,27 +2603,27 @@ class RegExpNativeCompiler {
return NULL; return NULL;
memcpy(bitmapData, charSet->u.bits, bitmapLen); 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)) if (!fails.append(to_fail))
return NULL; 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, 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))) { 0))) {
return NULL; 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* 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); ACC_READONLY);
LIns* bitMask = lir->ins2(LIR_lsh, lir->insImmI(1), LIns* bitMask = lir->ins2(LIR_lshi, lir->insImmI(1),
lir->ins2(LIR_and, text_ch, lir->insImmI(0x7))); lir->ins2(LIR_andi, text_ch, lir->insImmI(0x7)));
LIns* test = lir->ins2(LIR_eq, lir->ins2(LIR_and, byte, bitMask), lir->insImmI(0)); LIns* test = lir->ins2(LIR_eqi, lir->ins2(LIR_andi, byte, bitMask), lir->insImmI(0));
LIns* to_next = lir->insBranch(LIR_jt, test, 0); LIns* to_next = lir->insBranch(LIR_jt, test, 0);
if (!fails.append(to_next)) if (!fails.append(to_next))
return NULL; 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. */ /* Factor out common code to index js_alnum. */
@ -2631,44 +2631,44 @@ class RegExpNativeCompiler {
{ {
if (sizeof(bool) != 1) { if (sizeof(bool) != 1) {
LIns *sizeLog2 = lir->insImmI(StaticLog2<sizeof(bool)>::result); 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)); LIns *addr = lir->ins2(LIR_addp, lir->insImmP(tbl), lir->insUI2P(chr));
return lir->insLoad(LIR_ldzb, addr, 0, ACC_READONLY); return lir->insLoad(LIR_lduc2ui, addr, 0, ACC_READONLY);
} }
/* Compile a builtin character class. */ /* Compile a builtin character class. */
LIns *compileBuiltinClass(RENode *node, LIns *pos, LInsList &fails) LIns *compileBuiltinClass(RENode *node, LIns *pos, LInsList &fails)
{ {
/* All the builtins checked below consume one character. */ /* 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; 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) { switch (node->op) {
case REOP_DOT: case REOP_DOT:
{ {
/* Accept any character except those in ECMA-262 15.10.2.8. */ /* 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))) if (!fails.append(lir->insBranch(LIR_jt, eq1, NULL)))
return 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))) if (!fails.append(lir->insBranch(LIR_jt, eq2, NULL)))
return 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))) if (!fails.append(lir->insBranch(LIR_jt, eq3, NULL)))
return 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))) if (!fails.append(lir->insBranch(LIR_jt, eq4, NULL)))
return NULL; return NULL;
break; break;
} }
case REOP_DIGIT: 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))) if (!fails.append(lir->insBranch(LIR_jf, ge, NULL)))
return 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))) if (!fails.append(lir->insBranch(LIR_jf, le, NULL)))
return NULL; return NULL;
break; break;
@ -2676,9 +2676,9 @@ class RegExpNativeCompiler {
case REOP_NONDIGIT: case REOP_NONDIGIT:
{ {
/* Use 'and' to give a predictable branch for success path. */ /* Use 'and' to give a predictable branch for success path. */
LIns *ge = lir->ins2(LIR_ge, chr, lir->insImmI('0')); LIns *ge = lir->ins2(LIR_gei, chr, lir->insImmI('0'));
LIns *le = lir->ins2(LIR_le, chr, lir->insImmI('9')); LIns *le = lir->ins2(LIR_lei, chr, lir->insImmI('9'));
LIns *both = lir->ins2(LIR_and, ge, le); LIns *both = lir->ins2(LIR_andi, ge, le);
if (!fails.append(lir->insBranch(LIR_jf, lir->insEqI_0(both), NULL))) if (!fails.append(lir->insBranch(LIR_jf, lir->insEqI_0(both), NULL)))
return NULL; return NULL;
break; break;
@ -2689,7 +2689,7 @@ class RegExpNativeCompiler {
* Compile the condition: * Compile the condition:
* ((uint)*cp) < 128 && js_alnum[(uint)*cp] * ((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))) if (!fails.append(lir->insBranch(LIR_jf, rangeCnd, NULL)))
return NULL; return NULL;
LIns *tableVal = compileTableRead(chr, js_alnum); LIns *tableVal = compileTableRead(chr, js_alnum);
@ -2703,7 +2703,7 @@ class RegExpNativeCompiler {
* Compile the condition: * Compile the condition:
* ((uint)*cp) >= 128 || !js_alnum[(uint)*cp] * ((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 *rangeBr = lir->insBranch(LIR_jt, rangeCnd, NULL);
LIns *tableVal = compileTableRead(chr, js_alnum); LIns *tableVal = compileTableRead(chr, js_alnum);
if (!fails.append(lir->insBranch(LIR_jf, lir->insEqI_0(tableVal), NULL))) 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 * (200A, max): 2028, 2029, 202F, 205F, 3000
*/ */
/* Below 0x20? */ /* 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); LIns *tableRangeBr = lir->insBranch(LIR_jt, tableRangeCnd, NULL);
/* Fall through means *chr > 0x20. */ /* Fall through means *chr > 0x20. */
/* Handle (0x20,0xA0). */ /* 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); LIns *asciiMissBr = lir->insBranch(LIR_jt, asciiCnd, NULL);
/* Fall through means *chr >= 0xA0. */ /* Fall through means *chr >= 0xA0. */
/* Partition around [0x2000,0x200A]. */ /* 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 *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 *aboveBr = lir->insBranch(LIR_jt, aboveCnd, NULL);
LIns *intervalMatchBr = lir->insBranch(LIR_j, NULL, NULL); LIns *intervalMatchBr = lir->insBranch(LIR_j, NULL, NULL);
/* Handle [0xA0,0x2000). */ /* Handle [0xA0,0x2000). */
LIns *belowLbl = lir->ins0(LIR_label); LIns *belowLbl = lir->ins0(LIR_label);
belowBr->setTarget(belowLbl); 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 *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 *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 *eq3Br = lir->insBranch(LIR_jt, eq3Cnd, NULL);
LIns *belowMissBr = lir->insBranch(LIR_j, NULL, NULL); LIns *belowMissBr = lir->insBranch(LIR_j, NULL, NULL);
/* Handle (0x200A, max). */ /* Handle (0x200A, max). */
LIns *aboveLbl = lir->ins0(LIR_label); LIns *aboveLbl = lir->ins0(LIR_label);
aboveBr->setTarget(aboveLbl); 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 *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 *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 *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 *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 *eq8Br = lir->insBranch(LIR_jt, eq8Cnd, NULL);
LIns *aboveMissBr = lir->insBranch(LIR_j, NULL, NULL); LIns *aboveMissBr = lir->insBranch(LIR_j, NULL, NULL);
@ -2814,7 +2814,7 @@ class RegExpNativeCompiler {
return NULL; 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) 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. * we need to abort the loop or else we will loop forever.
*/ */
if (mayMatchEmpty(bodyRe)) { 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))) if (!kidFails.append(lir->insBranch(LIR_jt, eqCnd, NULL)))
return NULL; return NULL;
} }
@ -3012,9 +3012,9 @@ class RegExpNativeCompiler {
* conditionally executed, and we (currently) don't have real phi * conditionally executed, and we (currently) don't have real phi
* nodes, we need only consider insns defined in A and used in E. * nodes, we need only consider insns defined in A and used in E.
*/ */
lir->ins1(LIR_plive, state); lir->ins1(LIR_livep, state);
lir->ins1(LIR_plive, cpend); lir->ins1(LIR_livep, cpend);
lir->ins1(LIR_plive, start); lir->ins1(LIR_livep, start);
/* After the loop: reload 'pos' from memory and continue. */ /* After the loop: reload 'pos' from memory and continue. */
targetCurrentPoint(kidFails); targetCurrentPoint(kidFails);
@ -3083,13 +3083,13 @@ class RegExpNativeCompiler {
/* Fall-through from compileNode means success. */ /* Fall-through from compileNode means success. */
lir->insStore(pos, state, offsetof(REGlobalData, stateStack), ACC_OTHER); lir->insStore(pos, state, offsetof(REGlobalData, stateStack), ACC_OTHER);
lir->ins0(LIR_regfence); 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. */ /* Stick return here so we don't have to jump over it every time. */
if (anchorFail) { if (anchorFail) {
targetCurrentPoint(anchorFail); targetCurrentPoint(anchorFail);
lir->ins0(LIR_regfence); lir->ins0(LIR_regfence);
lir->ins1(LIR_ret, lir->insImmI(0)); lir->ins1(LIR_reti, lir->insImmI(0));
} }
/* Target failed matches. */ /* Target failed matches. */
@ -3105,7 +3105,7 @@ class RegExpNativeCompiler {
/* Failed to match on first character, so fail whole match. */ /* Failed to match on first character, so fail whole match. */
lir->ins0(LIR_regfence); lir->ins0(LIR_regfence);
lir->ins1(LIR_ret, lir->insImmI(0)); lir->ins1(LIR_reti, lir->insImmI(0));
return !outOfMemory(); return !outOfMemory();
} }
@ -3113,13 +3113,13 @@ class RegExpNativeCompiler {
bool compileAnchoring(RENode *root, LIns *start) bool compileAnchoring(RENode *root, LIns *start)
{ {
/* Guard outer anchoring loop. Use <= to allow empty regexp match. */ /* 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)) if (!compileRootNode(root, start, anchorFail))
return false; return false;
/* Outer loop increment. */ /* 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); offsetof(REGlobalData, skipped), ACC_OTHER);
return !outOfMemory(); return !outOfMemory();
@ -3144,8 +3144,8 @@ class RegExpNativeCompiler {
if (loopLabel) { if (loopLabel) {
lir->insBranch(LIR_j, NULL, loopLabel); lir->insBranch(LIR_j, NULL, loopLabel);
LirBuffer* lirbuf = fragment->lirbuf; LirBuffer* lirbuf = fragment->lirbuf;
lir->ins1(LIR_plive, lirbuf->state); lir->ins1(LIR_livep, lirbuf->state);
lir->ins1(LIR_plive, lirbuf->param1); lir->ins1(LIR_livep, lirbuf->param1);
} }
Allocator &alloc = *JS_TRACE_MONITOR(cx).dataAlloc; Allocator &alloc = *JS_TRACE_MONITOR(cx).dataAlloc;

Просмотреть файл

@ -8275,7 +8275,7 @@ TraceRecorder::i2d(LIns* i)
} }
LIns* LIns*
TraceRecorder::d2i(LIns* f) TraceRecorder::d2i(LIns* f, bool resultCanBeImpreciseIfFractional)
{ {
if (f->isImmD()) if (f->isImmD())
return lir->insImmI(js_DoubleToECMAInt32(f->immD())); 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_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* LIns*
@ -8333,7 +8335,10 @@ TraceRecorder::makeNumberInt32(LIns* f)
JS_ASSERT(f->isD()); JS_ASSERT(f->isD());
LIns* x; LIns* x;
if (!isPromote(f)) { 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); guard(true, lir->ins2(LIR_feq, f, lir->ins1(LIR_i2f, x)), MISMATCH_EXIT);
} else { } else {
x = demote(lir, f); 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). */ /* If not idx < min(length, capacity), stay on trace (and read value as undefined). */
JS_ASSERT(obj->isDenseArrayMinLenCapOk());
LIns* minLenCap = LIns* minLenCap =
addName(stobj_get_fslot(obj_ins, JSObject::JSSLOT_DENSE_ARRAY_MINLENCAP), "minLenCap"); addName(stobj_get_fslot(obj_ins, JSObject::JSSLOT_DENSE_ARRAY_MINLENCAP), "minLenCap");
LIns* br2 = lir->insBranch(LIR_jf, 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). */ /* Guard array min(length, capacity). */
JS_ASSERT(obj->isDenseArrayMinLenCapOk());
LIns* minLenCap = LIns* minLenCap =
addName(stobj_get_fslot(obj_ins, JSObject::JSSLOT_DENSE_ARRAY_MINLENCAP), "minLenCap"); addName(stobj_get_fslot(obj_ins, JSObject::JSSLOT_DENSE_ARRAY_MINLENCAP), "minLenCap");
guard(true, guard(true,

Просмотреть файл

@ -1186,7 +1186,7 @@ class TraceRecorder
nanojit::LIns* s0, nanojit::LIns* s1); nanojit::LIns* s0, nanojit::LIns* s1);
nanojit::LIns* i2d(nanojit::LIns* i); 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); nanojit::LIns* f2u(nanojit::LIns* f);
JS_REQUIRES_STACK nanojit::LIns* makeNumberInt32(nanojit::LIns* f); JS_REQUIRES_STACK nanojit::LIns* makeNumberInt32(nanojit::LIns* f);
JS_REQUIRES_STACK nanojit::LIns* stringify(jsval& v); 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 JSInt64
PRMJ_Now(void) PRMJ_Now(void)
{ {
@ -424,8 +429,7 @@ PRMJ_Now(void)
This does not appear to be needed on Vista as the timeBegin/timeEndPeriod This does not appear to be needed on Vista as the timeBegin/timeEndPeriod
calls seem to immediately take effect. */ calls seem to immediately take effect. */
int thiscall = JS_ATOMIC_INCREMENT(&nCalls); int thiscall = JS_ATOMIC_INCREMENT(&nCalls);
/* 10 seems to be the number of calls to load with a blank homepage */ if (thiscall <= CALIBRATION_DELAY_COUNT) {
if (thiscall <= 10) {
LowResTime(&ft); LowResTime(&ft);
return (FILETIME2INT64(ft)-win2un)/10L; return (FILETIME2INT64(ft)-win2un)/10L;
} }

Просмотреть файл

@ -3658,6 +3658,34 @@ Elapsed(JSContext *cx, uintN argc, jsval *vp)
return JS_FALSE; 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 #ifdef XP_UNIX
#include <fcntl.h> #include <fcntl.h>
@ -3911,6 +3939,7 @@ static JSFunctionSpec shell_functions[] = {
JS_FN("parse", Parse, 1,0), JS_FN("parse", Parse, 1,0),
JS_FN("timeout", Timeout, 1,0), JS_FN("timeout", Timeout, 1,0),
JS_FN("elapsed", Elapsed, 0,0), JS_FN("elapsed", Elapsed, 0,0),
JS_FN("parent", Parent, 1,0),
JS_FS_END JS_FS_END
}; };
@ -4018,7 +4047,8 @@ static const char *const shell_help_messages[] = {
"timeout([seconds])\n" "timeout([seconds])\n"
" Get/Set the limit in seconds for the execution time for the current context.\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.", " 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. */ /* Help messages must match shell functions. */
@ -4980,6 +5010,13 @@ main(int argc, char **argv, char **envp)
argc--; argc--;
argv++; 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); rt = JS_NewRuntime(64L * 1024L * 1024L);
if (!rt) if (!rt)
return 1; return 1;

Просмотреть файл

@ -37,7 +37,7 @@
gTestfile = 'regress-313080.js'; 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 BUGNUMBER = 313080;
var actual = 'No Crash'; var actual = 'No Crash';
var expect = 'No Crash'; var expect = 'No Crash';
@ -48,7 +48,6 @@ START(summary);
try try
{ {
<element/>.__proto__(); <element/>.__proto__();
<element/>.__parent__();
<element/>.function::__proto__(); <element/>.function::__proto__();
} }
catch(e) catch(e)

Просмотреть файл

@ -38,7 +38,7 @@
var gTestfile = '7.4-01.js'; var gTestfile = '7.4-01.js';
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
var BUGNUMBER = 475834; 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 actual = '';
var expect = ''; 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() + "..."); print("Starting test with old descriptor " + old.toSource() + "...");
for (var j = 0, sz2 = VALID_DESCRIPTORS.length; j < sz2; j++) 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!"); " 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 // HELPERS
@ -600,7 +701,7 @@ TestRunner.prototype =
print("Starting test with old descriptor " + old.toSource() + "..."); print("Starting test with old descriptor " + old.toSource() + "...");
for (var j = 0, sz2 = VALID_DESCRIPTORS.length; j < sz2; j++) 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) _runTestSet: function _runTestSet(fun, completeMessage)
@ -724,7 +825,8 @@ TestRunner.prototype =
return; return;
} }
}, },
_runSinglePropertyPresentTest: function _runSinglePropertyPresentTest(old, add) _runSinglePropertyPresentTest:
function _runSinglePropertyPresentTest(old, add, middleDefines)
{ {
var nativeObj = NativeTest.newObject(); var nativeObj = NativeTest.newObject();
var reimplObj = ReimplTest.newObject(); var reimplObj = ReimplTest.newObject();
@ -781,6 +883,35 @@ TestRunner.prototype =
return; 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 try
{ {
NativeTest.defineProperty(nativeObj, "foo", add); 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 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.7-01.js
script 15.2.3.14-01.js # does not use reportCompare 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-164697.js
script regress-178722.js script regress-178722.js
script regress-192465.js script regress-192465.js
script regress-220584.js
script regress-225831.js script regress-225831.js
script regress-226078.js script regress-226078.js
script regress-226507.js script regress-226507.js
@ -32,7 +31,6 @@ script regress-311161.js
script regress-311583.js script regress-311583.js
script regress-311792-01.js script regress-311792-01.js
script regress-311792-02.js script regress-311792-02.js
script regress-312278.js
script regress-313500.js script regress-313500.js
script regress-313763.js script regress-313763.js
script regress-313803.js script regress-313803.js
@ -196,7 +194,6 @@ script regress-452168.js
script regress-452178.js script regress-452178.js
script regress-452329.js script regress-452329.js
script regress-452338.js script regress-452338.js
script regress-452372.js
script regress-452565.js script regress-452565.js
script regress-453249.js script regress-453249.js
script regress-454040.js script regress-454040.js

Просмотреть файл

@ -38,7 +38,7 @@
var gTestfile = 'regress-164697.js'; var gTestfile = 'regress-164697.js';
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
var BUGNUMBER = 164697; var BUGNUMBER = 164697;
var summary = '(instance.__parent__ == constructor.__parent__)'; var summary = '(parent(instance) == parent(constructor))';
var actual = ''; var actual = '';
var expect = ''; var expect = '';
@ -61,13 +61,10 @@ runtest('new Function(";")', 'Function');
runtest('[]', 'Array'); runtest('[]', 'Array');
runtest('new Array()', 'Array'); runtest('new Array()', 'Array');
runtest('""', 'String');
runtest('new String()', 'String'); runtest('new String()', 'String');
runtest('true', 'Boolean');
runtest('new Boolean()', 'Boolean'); runtest('new Boolean()', 'Boolean');
runtest('1', 'Number');
runtest('new Number("1")', 'Number'); runtest('new Number("1")', 'Number');
runtest('new Date()', 'Date'); runtest('new Date()', 'Date');
@ -82,19 +79,23 @@ function runtest(myinstance, myconstructor)
var expr; var expr;
var actual; var actual;
try if (typeof parent === "function")
{ {
expr = '(' + myinstance + ').__parent__ == ' + try
myconstructor + '.__parent__'; {
printStatus(expr); expr =
actual = eval(expr).toString(); 'parent(' + myinstance + ') == ' +
} 'parent(' + myconstructor + ')';
catch(ex) printStatus(expr);
{ actual = eval(expr).toString();
actual = ex + ''; }
} catch(ex)
{
actual = ex + '';
}
reportCompare(expect, actual, expr); reportCompare(expect, actual, expr);
}
try 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-355145.js
script regress-355410.js script regress-355410.js
script regress-355512.js script regress-355512.js
script regress-355578.js
script regress-355583.js script regress-355583.js
script regress-363040-01.js script regress-363040-01.js
script regress-363040-02.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 try
{ {
(function() { (function() {
let b = function(){}.__parent__; let b = parent(function(){});
print(b[1] = throwError); print(b[1] = throwError);
})(); })();
} }

Просмотреть файл

@ -27,7 +27,7 @@ function makeWorkerFn(id) {
for (n in bar) { for (n in bar) {
for (m in bar[n]) {} for (m in bar[n]) {}
} }
for (n in {}.__parent__) {} for (n in parent({})) {}
}; };
} }
@ -42,8 +42,8 @@ var actual;
expect = actual = 'No crash'; expect = actual = 'No crash';
if (typeof scatter == 'undefined') { if (typeof scatter == 'undefined') {
print('Test skipped. scatter not defined.'); print('Test skipped. scatter not defined.');
} else if (!("__parent__" in {})) { } else if (typeof parent === "undefined") {
print('Test skipped. __parent__ not defined.'); print('Test skipped, no parent() function.');
} else { } else {
for (let i = 0; i < LOOP_COUNT; i++) { for (let i = 0; i < LOOP_COUNT; i++) {
foo = 0; foo = 0;

Просмотреть файл

@ -8,9 +8,14 @@ script regress-541255-3.js
script regress-541255-4.js script regress-541255-4.js
script regress-541455.js script regress-541455.js
script regress-546615.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 script regress-555246-0.js
fails script regress-555246-1.js fails script regress-555246-1.js
script regress-559438.js script regress-559438.js
script regress-560101.js script regress-560101.js
script regress-560998-1.js script regress-560998-1.js
script regress-560998-2.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. * 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. * @return the corresponding global.
*/ */
void /* JSObject */ getGlobalForObject(/* in JSObject obj */); void /* JSObject */ getGlobalForObject(/* in JSObject obj */);

Просмотреть файл

@ -759,6 +759,24 @@ Options(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
return JS_TRUE; 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[] = { static JSFunctionSpec glob_functions[] = {
{"print", Print, 0,0,0}, {"print", Print, 0,0,0},
{"readline", ReadLine, 1,0,0}, {"readline", ReadLine, 1,0,0},
@ -774,6 +792,7 @@ static JSFunctionSpec glob_functions[] = {
#endif #endif
{"clear", Clear, 1,0,0}, {"clear", Clear, 1,0,0},
{"options", Options, 0,0,0}, {"options", Options, 0,0,0},
JS_FN("parent", Parent, 1,0),
#ifdef DEBUG #ifdef DEBUG
{"dumpHeap", DumpHeap, 5,0,0}, {"dumpHeap", DumpHeap, 5,0,0},
#endif #endif

Просмотреть файл

@ -594,9 +594,8 @@ XPC_COW_GetOrSetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp,
} }
if (interned_id == GetRTIdByIndex(cx, XPCJSRuntime::IDX_PROTO) || if (interned_id == GetRTIdByIndex(cx, XPCJSRuntime::IDX_PROTO) ||
interned_id == GetRTIdByIndex(cx, XPCJSRuntime::IDX_PARENT) ||
interned_id == GetRTIdByIndex(cx, XPCJSRuntime::IDX_EXPOSEDPROPS)) { 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 return ThrowException(NS_ERROR_INVALID_ARG, cx); // XXX better error message
} }

Просмотреть файл

@ -1382,7 +1382,7 @@ XPCNativeWrapper::CreateExplicitWrapper(JSContext *cx,
// parents for it. // parents for it.
JS_LockGCThing(cx, wrapperObj); 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. // XPCWrappedNative's chain.
if (!MirrorWrappedNativeParent(cx, wrappedNative, &parent)) if (!MirrorWrappedNativeParent(cx, wrappedNative, &parent))
return JS_FALSE; return JS_FALSE;

Просмотреть файл

@ -62,7 +62,6 @@ const char* XPCJSRuntime::mStrings[] = {
"item", // IDX_ITEM "item", // IDX_ITEM
"__proto__", // IDX_PROTO "__proto__", // IDX_PROTO
"__iterator__", // IDX_ITERATOR "__iterator__", // IDX_ITERATOR
"__parent__", // IDX_PARENT
"__exposedProps__" // IDX_EXPOSEDPROPS "__exposedProps__" // IDX_EXPOSEDPROPS
}; };

Просмотреть файл

@ -669,7 +669,6 @@ public:
IDX_ITEM , IDX_ITEM ,
IDX_PROTO , IDX_PROTO ,
IDX_ITERATOR , IDX_ITERATOR ,
IDX_PARENT ,
IDX_EXPOSEDPROPS , IDX_EXPOSEDPROPS ,
IDX_TOTAL_COUNT // just a count of the above IDX_TOTAL_COUNT // just a count of the above
}; };
@ -3013,7 +3012,7 @@ public:
* @param s the native object we're working with * @param s the native object we're working with
* @param type the type of object that s is * @param type the type of object that s is
* @param iid the interface of s that we want * @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 * chain
* @param pErr [out] relevant error code, if any. * @param pErr [out] relevant error code, if any.
*/ */
@ -3044,8 +3043,7 @@ public:
* @param Interface the interface of src that we want * @param Interface the interface of src that we want
* @param cache the wrapper cache for src (may be null, in which case src * @param cache the wrapper cache for src (may be null, in which case src
* will be QI'ed to get the cache) * will be QI'ed to get the cache)
* @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
* chain
* @param allowNativeWrapper if true, this method may wrap the resulting * @param allowNativeWrapper if true, this method may wrap the resulting
* JSObject in an XPCNativeWrapper and return that, as needed. * JSObject in an XPCNativeWrapper and return that, as needed.
* @param isGlobal * @param isGlobal
@ -3100,8 +3098,7 @@ public:
* @param type the type of objects in the array * @param type the type of objects in the array
* @param iid the interface of each object in the array that we want * @param iid the interface of each object in the array that we want
* @param count the number of items in the array * @param count the number of items in the array
* @param scope the default scope to put on the new JSObjects' __parent__ * @param scope the default scope to put on the new JSObjects' parent chain
* chain
* @param pErr [out] relevant error code, if any. * @param pErr [out] relevant error code, if any.
*/ */
static JSBool NativeArray2JS(XPCLazyCallContext& ccx, static JSBool NativeArray2JS(XPCLazyCallContext& ccx,
@ -4275,8 +4272,7 @@ public:
* *
* @param ccx the context for the whole procedure * @param ccx the context for the whole procedure
* @param variant the variant to convert * @param variant the variant to convert
* @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
* chain
* @param pErr [out] relevant error code, if any. * @param pErr [out] relevant error code, if any.
* @param pJSVal [out] the resulting jsval. * @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); .getInterface(Components.interfaces.nsIDOMWindowUtils);
ok(utils.getClassName(wrapper) === expected, note); 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) { function run_test(ok, xpcnw, sjow) {
// both wrappers should point to our window: XOW // both wrappers should point to our window: XOW
check_wrapper(ok, ok, "Function", "functions are wrapped properly") 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, xpcnw, "XPCCrossOriginWrapper", "XPCNWs are transformed correctly");
check_wrapper(ok, sjow, "XPCCrossOriginWrapper", "SJOWs are transformed correctly"); check_wrapper(ok, sjow, "XPCCrossOriginWrapper", "SJOWs are transformed correctly");

Просмотреть файл

@ -62,8 +62,7 @@ function COWTests() {
var empty = {}; var empty = {};
isProp(getCOW(empty), "foo", undefined, "empty.foo is undefined"); isProp(getCOW(empty), "foo", undefined, "empty.foo is undefined");
const PROPS_TO_TEST = ['foo', '__parent__', '__proto__', const PROPS_TO_TEST = ['foo', '__proto__', 'prototype', 'constructor'];
'prototype', 'constructor'];
var strict = { __exposedProps__: {} }; var strict = { __exposedProps__: {} };
var strictCOW = getCOW(strict); var strictCOW = getCOW(strict);

Просмотреть файл

@ -20,11 +20,17 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=366645
/** Test for Bug 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'); netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
var Cc = Components.classes; var Cc = Components.classes;
var Ci = Components.interfaces; var Ci = Components.interfaces;
var table = Cc["@mozilla.org/url-classifier/table;1?type=url"].createInstance(); 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"); ok(!!componentScope, "unable to get wrapped js object");
var PROT_EnchashDecrypter = componentScope.PROT_EnchashDecrypter; var PROT_EnchashDecrypter = componentScope.PROT_EnchashDecrypter;

Просмотреть файл

@ -45,6 +45,18 @@ const Ci = Components.interfaces;
#expand const CTYPES_TEST_LIB = __CTYPES_TEST_LIB__; #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) function do_check_throws(f, type, stack)
{ {
if (!stack) if (!stack)
@ -233,16 +245,20 @@ function run_abstract_class_tests()
do_check_class(ctypes.CType, "Function"); do_check_class(ctypes.CType, "Function");
do_check_class(ctypes.CType.prototype, "CType"); do_check_class(ctypes.CType.prototype, "CType");
do_check_true(ctypes.CType.__parent__ === ctypes); checkParentIsCTypes(ctypes.CType);
do_check_true(ctypes.CType.__proto__ === ctypes.__parent__.Function.prototype); getParent(ctypes, function(p) {
do_check_true(ctypes.CType instanceof ctypes.__parent__.Function); 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_true(ctypes.CType.hasOwnProperty("prototype"));
do_check_throws(function() { ctypes.CType.prototype(); }, Error); do_check_throws(function() { ctypes.CType.prototype(); }, Error);
do_check_throws(function() { new ctypes.CType.prototype() }, Error); do_check_throws(function() { new ctypes.CType.prototype() }, Error);
do_check_true(ctypes.CType.prototype.__parent__ === ctypes); checkParentIsCTypes(ctypes.CType.prototype);
do_check_true(ctypes.CType.prototype.__proto__ === ctypes.__parent__.Function.prototype); getParent(ctypes, function(p) {
do_check_true(ctypes.CType.prototype instanceof ctypes.__parent__.Function); 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.hasOwnProperty("constructor"));
do_check_true(ctypes.CType.prototype.constructor === ctypes.CType); 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, "Function");
do_check_class(ctypes.CData.prototype, "CData"); 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.__proto__ === ctypes.CType.prototype);
do_check_true(ctypes.CData instanceof ctypes.CType); do_check_true(ctypes.CData instanceof ctypes.CType);
do_check_true(ctypes.CData.hasOwnProperty("prototype")); do_check_true(ctypes.CData.hasOwnProperty("prototype"));
do_check_true(ctypes.CData.prototype.__parent__ === ctypes); checkParentIsCTypes(ctypes.CData.prototype);
do_check_true(ctypes.CData.prototype.__proto__ === ctypes.__parent__.Object.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.hasOwnProperty("constructor"));
do_check_true(ctypes.CData.prototype.constructor === ctypes.CData); 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, "Function");
do_check_class(ctypes.Int64.prototype, "Int64"); do_check_class(ctypes.Int64.prototype, "Int64");
do_check_true(ctypes.Int64.__parent__ === ctypes); checkParentIsCTypes(ctypes.Int64);
do_check_true(ctypes.Int64.__proto__ === ctypes.__parent__.Function.prototype); 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.hasOwnProperty("prototype"));
do_check_true(ctypes.Int64.prototype.__parent__ === ctypes); checkParentIsCTypes(ctypes.Int64.prototype);
do_check_true(ctypes.Int64.prototype.__proto__ === ctypes.__parent__.Object.prototype);
do_check_true(ctypes.Int64.prototype.hasOwnProperty("constructor")); do_check_true(ctypes.Int64.prototype.hasOwnProperty("constructor"));
do_check_true(ctypes.Int64.prototype.constructor === ctypes.Int64); 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); do_check_throws(function() { ctypes.Int64.prototype.toSource(); }, Error);
let i = ctypes.Int64(0); 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.__proto__ === ctypes.Int64.prototype);
do_check_true(i instanceof ctypes.Int64); 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, "Function");
do_check_class(ctypes.UInt64.prototype, "UInt64"); do_check_class(ctypes.UInt64.prototype, "UInt64");
do_check_true(ctypes.UInt64.__parent__ === ctypes); checkParentIsCTypes(ctypes.UInt64);
do_check_true(ctypes.UInt64.__proto__ === ctypes.__parent__.Function.prototype); 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.hasOwnProperty("prototype"));
do_check_true(ctypes.UInt64.prototype.__parent__ === ctypes); checkParentIsCTypes(ctypes.UInt64.prototype);
do_check_true(ctypes.UInt64.prototype.__proto__ === ctypes.__parent__.Object.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.hasOwnProperty("constructor"));
do_check_true(ctypes.UInt64.prototype.constructor === ctypes.UInt64); 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); do_check_throws(function() { ctypes.UInt64.prototype.toSource(); }, Error);
let i = ctypes.UInt64(0); 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.__proto__ === ctypes.UInt64.prototype);
do_check_true(i instanceof ctypes.UInt64); 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, "CType");
do_check_class(t.prototype, "CData"); 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.__proto__ === ctypes.CType.prototype);
do_check_true(t instanceof ctypes.CType); 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.__proto__ === ctypes.CData.prototype);
do_check_true(t.prototype instanceof ctypes.CData); do_check_true(t.prototype instanceof ctypes.CData);
do_check_true(t.prototype.constructor === t); 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. // Test that an instance 'd' of 't' is a CData.
let d = t(); let d = t();
do_check_class(d, "CData"); do_check_class(d, "CData");
do_check_true(d.__parent__ === ctypes); checkParentIsCTypes(d);
do_check_true(d.__proto__ === t.prototype); do_check_true(d.__proto__ === t.prototype);
do_check_true(d instanceof t); do_check_true(d instanceof t);
do_check_true(d.constructor === 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, "Function");
do_check_class(c.prototype, "CType"); do_check_class(c.prototype, "CType");
do_check_true(c.__parent__ === ctypes); checkParentIsCTypes(c);
do_check_true(c.__proto__ === ctypes.__parent__.Function.prototype); getParent(ctypes, function(p) {
do_check_true(c instanceof ctypes.__parent__.Function); 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.__proto__ === ctypes.CType.prototype);
do_check_true(c.prototype instanceof ctypes.CType); do_check_true(c.prototype instanceof ctypes.CType);
do_check_true(c.prototype.constructor === c); 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, "CType");
do_check_class(t.prototype, "CData"); 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.__proto__ === c.prototype);
do_check_true(t instanceof c); do_check_true(t instanceof c);
do_check_true(t.prototype.__parent__ === ctypes); checkParentIsCTypes(t.prototype);
do_check_class(t.prototype.__proto__, "CData"); do_check_class(t.prototype.__proto__, "CData");
// 't.prototype.__proto__' is the common ancestor of all types constructed // 't.prototype.__proto__' is the common ancestor of all types constructed
// from 'c'; while not available from 'c' directly, it should be identically // from 'c'; while not available from 'c' directly, it should be identically
// equal to 't2.prototype.__proto__' where 't2' is a different CType // equal to 't2.prototype.__proto__' where 't2' is a different CType
// constructed from 'c'. // constructed from 'c'.
do_check_true(t.prototype.__proto__ === t2.prototype.__proto__); 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.__proto__.__proto__ === ctypes.CData.prototype);
do_check_true(t.prototype instanceof ctypes.CData); do_check_true(t.prototype instanceof ctypes.CData);
do_check_true(t.prototype.constructor === t); 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) { if (t.__proto__ != ctypes.FunctionType.prototype) {
let d = t(); let d = t();
do_check_class(d, "CData"); do_check_class(d, "CData");
do_check_true(d.__parent__ === ctypes); checkParentIsCTypes(d);
do_check_true(d.__proto__ === t.prototype); do_check_true(d.__proto__ === t.prototype);
do_check_true(d instanceof t); do_check_true(d instanceof t);
do_check_true(d.constructor === t); do_check_true(d.constructor === t);

Просмотреть файл

@ -18,11 +18,17 @@ mochitest framework.
<script class="testbody" type="text/javascript"> <script class="testbody" type="text/javascript">
<![CDATA[ <![CDATA[
function getParent(obj) {
return window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindowUtils)
.getParent(obj);
}
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect'); netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
var Cc = Components.classes; var Cc = Components.classes;
var Ci = Components.interfaces; var Ci = Components.interfaces;
var table = Cc["@mozilla.org/url-classifier/table;1?type=url"].createInstance(); 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"); ok(!!componentScope, "unable to get wrapped js object");
////// Test PROT_EnchashDecrypter methods ////// ////// Test PROT_EnchashDecrypter methods //////