mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-08 04:27:37 +00:00
Fast native constructors, bug 579471.
This commit is contained in:
parent
9aab972de1
commit
b02ce0b886
@ -1008,7 +1008,8 @@ Class js_ArrayClass = {
|
||||
"Array",
|
||||
Class::NON_NATIVE |
|
||||
JSCLASS_HAS_RESERVED_SLOTS(JSObject::DENSE_ARRAY_FIXED_RESERVED_SLOTS) |
|
||||
JSCLASS_HAS_CACHED_PROTO(JSProto_Array),
|
||||
JSCLASS_HAS_CACHED_PROTO(JSProto_Array) |
|
||||
JSCLASS_FAST_CONSTRUCTOR,
|
||||
PropertyStub, /* addProperty */
|
||||
PropertyStub, /* delProperty */
|
||||
PropertyStub, /* getProperty */
|
||||
@ -1043,7 +1044,9 @@ Class js_ArrayClass = {
|
||||
|
||||
Class js_SlowArrayClass = {
|
||||
"Array",
|
||||
JSCLASS_HAS_PRIVATE | JSCLASS_HAS_CACHED_PROTO(JSProto_Array),
|
||||
JSCLASS_HAS_PRIVATE |
|
||||
JSCLASS_HAS_CACHED_PROTO(JSProto_Array) |
|
||||
JSCLASS_FAST_CONSTRUCTOR,
|
||||
slowarray_addProperty,
|
||||
PropertyStub, /* delProperty */
|
||||
PropertyStub, /* getProperty */
|
||||
@ -2959,31 +2962,29 @@ NewDenseArrayObject(JSContext *cx)
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_Array(JSContext *cx, JSObject *obj, uintN argc, Value *argv, Value *rval)
|
||||
js_Array(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
jsuint length;
|
||||
const Value *vector;
|
||||
|
||||
/* If called without new, replace obj with a new Array object. */
|
||||
if (!JS_IsConstructing(cx)) {
|
||||
obj = NewDenseArrayObject(cx);
|
||||
if (!obj)
|
||||
return JS_FALSE;
|
||||
rval->setObject(*obj);
|
||||
}
|
||||
/* Whether called with 'new' or not, use a new Array object. */
|
||||
JSObject *obj = NewObject(cx, &js_ArrayClass, NULL, NULL);
|
||||
if (!obj)
|
||||
return JS_FALSE;
|
||||
vp->setObject(*obj);
|
||||
|
||||
if (argc == 0) {
|
||||
length = 0;
|
||||
vector = NULL;
|
||||
} else if (argc > 1) {
|
||||
length = (jsuint) argc;
|
||||
vector = argv;
|
||||
} else if (!argv[0].isNumber()) {
|
||||
vector = vp + 2;
|
||||
} else if (!vp[2].isNumber()) {
|
||||
length = 1;
|
||||
vector = argv;
|
||||
vector = vp + 2;
|
||||
} else {
|
||||
length = ValueIsLength(cx, &argv[0]);
|
||||
if (argv[0].isNull())
|
||||
length = ValueIsLength(cx, vp + 2);
|
||||
if (vp[2].isNull())
|
||||
return JS_FALSE;
|
||||
vector = NULL;
|
||||
}
|
||||
@ -3033,7 +3034,7 @@ JS_DEFINE_CALLINFO_3(extern, OBJECT, js_NewPreallocatedArray, CONTEXT, OBJECT, I
|
||||
JSObject *
|
||||
js_InitArrayClass(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
JSObject *proto = js_InitClass(cx, obj, NULL, &js_ArrayClass, js_Array, 1,
|
||||
JSObject *proto = js_InitClass(cx, obj, NULL, &js_ArrayClass, (Native) js_Array, 1,
|
||||
NULL, array_methods, NULL, array_static_methods);
|
||||
if (!proto)
|
||||
return NULL;
|
||||
|
@ -239,7 +239,7 @@ js_GetDenseArrayElementValue(JSContext *cx, JSObject *obj, jsid id,
|
||||
|
||||
/* Array constructor native. Exposed only so the JIT can know its address. */
|
||||
JSBool
|
||||
js_Array(JSContext* cx, JSObject* obj, uintN argc, js::Value* argv, js::Value* rval);
|
||||
js_Array(JSContext *cx, uintN argc, js::Value *vp);
|
||||
|
||||
/*
|
||||
* Friend api function that allows direct creation of an array object with a
|
||||
|
@ -484,7 +484,8 @@ msFromTime(jsdouble t)
|
||||
Class js_DateClass = {
|
||||
js_Date_str,
|
||||
JSCLASS_HAS_RESERVED_SLOTS(JSObject::DATE_FIXED_RESERVED_SLOTS) |
|
||||
JSCLASS_HAS_CACHED_PROTO(JSProto_Date),
|
||||
JSCLASS_HAS_CACHED_PROTO(JSProto_Date) |
|
||||
JSCLASS_FAST_CONSTRUCTOR,
|
||||
PropertyStub, /* addProperty */
|
||||
PropertyStub, /* delProperty */
|
||||
PropertyStub, /* getProperty */
|
||||
@ -2302,28 +2303,28 @@ static JSFunctionSpec date_methods[] = {
|
||||
};
|
||||
|
||||
JSBool
|
||||
js_Date(JSContext *cx, JSObject *obj, uintN argc, Value *argv, Value *rval)
|
||||
js_Date(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
/* Date called as function. */
|
||||
if (!JS_IsConstructing(cx))
|
||||
return date_format(cx, NowAsMillis(), FORMATSPEC_FULL, rval);
|
||||
if (!vp[1].isMagic(JS_FAST_CONSTRUCTOR))
|
||||
return date_format(cx, NowAsMillis(), FORMATSPEC_FULL, vp);
|
||||
|
||||
/* Date called as constructor. */
|
||||
jsdouble d;
|
||||
if (argc == 0) {
|
||||
d = NowAsMillis();
|
||||
} else if (argc == 1) {
|
||||
if (!argv[0].isString()) {
|
||||
if (!vp[2].isString()) {
|
||||
/* the argument is a millisecond number */
|
||||
if (!ValueToNumber(cx, argv[0], &d))
|
||||
if (!ValueToNumber(cx, vp[2], &d))
|
||||
return JS_FALSE;
|
||||
d = TIMECLIP(d);
|
||||
} else {
|
||||
/* the argument is a string; parse it. */
|
||||
JSString *str = js_ValueToString(cx, argv[0]);
|
||||
JSString *str = js_ValueToString(cx, vp[2]);
|
||||
if (!str)
|
||||
return JS_FALSE;
|
||||
argv[0].setString(str);
|
||||
vp[2].setString(str);
|
||||
|
||||
if (!date_parseString(str, &d, cx))
|
||||
d = js_NaN;
|
||||
@ -2332,7 +2333,7 @@ js_Date(JSContext *cx, JSObject *obj, uintN argc, Value *argv, Value *rval)
|
||||
}
|
||||
} else {
|
||||
jsdouble msec_time;
|
||||
if (!date_msecFromArgs(cx, argc, argv, &msec_time))
|
||||
if (!date_msecFromArgs(cx, argc, vp + 2, &msec_time))
|
||||
return JS_FALSE;
|
||||
|
||||
if (JSDOUBLE_IS_FINITE(msec_time)) {
|
||||
@ -2341,7 +2342,13 @@ js_Date(JSContext *cx, JSObject *obj, uintN argc, Value *argv, Value *rval)
|
||||
}
|
||||
d = msec_time;
|
||||
}
|
||||
return SetUTCTime(cx, obj, d);
|
||||
|
||||
JSObject *obj = js_NewDateObjectMsec(cx, d);
|
||||
if (!obj)
|
||||
return JS_FALSE;
|
||||
vp->setObject(*obj);
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSObject *
|
||||
@ -2349,7 +2356,7 @@ js_InitDateClass(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
/* set static LocalTZA */
|
||||
LocalTZA = -(PRMJ_LocalGMTDifference() * msPerSecond);
|
||||
JSObject *proto = js_InitClass(cx, obj, NULL, &js_DateClass, js_Date, MAXARGS,
|
||||
JSObject *proto = js_InitClass(cx, obj, NULL, &js_DateClass, (Native) js_Date, MAXARGS,
|
||||
NULL, date_methods, NULL, date_static_methods);
|
||||
if (!proto)
|
||||
return NULL;
|
||||
|
@ -132,6 +132,6 @@ js_IntervalNow();
|
||||
|
||||
/* Date constructor native. Exposed only so the JIT can know its address. */
|
||||
JSBool
|
||||
js_Date(JSContext *cx, JSObject *obj, uintN argc, js::Value *argv, js::Value *rval);
|
||||
js_Date(JSContext *cx, uintN argc, js::Value *vp);
|
||||
|
||||
#endif /* jsdate_h___ */
|
||||
|
@ -2460,7 +2460,8 @@ js_NewFunction(JSContext *cx, JSObject *funobj, Native native, uintN nargs,
|
||||
|
||||
/* Initialize all function members. */
|
||||
fun->nargs = uint16(nargs);
|
||||
fun->flags = flags & (JSFUN_FLAGS_MASK | JSFUN_KINDMASK | JSFUN_TRCINFO);
|
||||
fun->flags = flags & (JSFUN_FLAGS_MASK | JSFUN_KINDMASK |
|
||||
JSFUN_TRCINFO | JSFUN_FAST_NATIVE_CTOR);
|
||||
if ((flags & JSFUN_KINDMASK) >= JSFUN_INTERPRETED) {
|
||||
JS_ASSERT(!native);
|
||||
JS_ASSERT(nargs == 0);
|
||||
@ -2604,7 +2605,8 @@ js_DefineFunction(JSContext *cx, JSObject *obj, JSAtom *atom, Native native,
|
||||
} else {
|
||||
gsop = NULL;
|
||||
}
|
||||
fun = js_NewFunction(cx, NULL, native, nargs, attrs, obj, atom);
|
||||
fun = js_NewFunction(cx, NULL, native, nargs,
|
||||
attrs & (JSFUN_FLAGS_MASK | JSFUN_TRCINFO), obj, atom);
|
||||
if (!fun)
|
||||
return NULL;
|
||||
if (!obj->defineProperty(cx, ATOM_TO_JSID(atom), ObjectValue(*fun),
|
||||
|
@ -101,6 +101,17 @@ typedef union JSLocalNames {
|
||||
appear to call itself via its own name
|
||||
or arguments.callee */
|
||||
|
||||
#define JSFUN_FAST_NATIVE_CTOR 0x0002 /* JSFastNative directly invokable
|
||||
* during construction. */
|
||||
|
||||
/*
|
||||
* Extra JSCLASS flag indicating the native passed to JS_InitClass is
|
||||
* a fast native constructor. This is internal for now as the 'this' value passed
|
||||
* to such a constructor is a magic value, and there is no way to query this
|
||||
* in the API. See bug 581263.
|
||||
*/
|
||||
#define JSCLASS_FAST_CONSTRUCTOR (1<<4)
|
||||
|
||||
#define JSFUN_EXPR_CLOSURE 0x1000 /* expression closure: function(x) x*x */
|
||||
#define JSFUN_TRCINFO 0x2000 /* when set, u.n.trcinfo is non-null,
|
||||
JSFunctionSpec::call points to a
|
||||
@ -165,12 +176,13 @@ struct JSFunction : public JSObject
|
||||
} u;
|
||||
JSAtom *atom; /* name for diagnostics and decompiling */
|
||||
|
||||
bool optimizedClosure() const { return FUN_KIND(this) > JSFUN_INTERPRETED; }
|
||||
bool needsWrapper() const { return FUN_NULL_CLOSURE(this) && u.i.skipmin != 0; }
|
||||
bool isInterpreted() const { return FUN_INTERPRETED(this); }
|
||||
bool isFastNative() const { return !!(flags & JSFUN_FAST_NATIVE); }
|
||||
bool isHeavyweight() const { return JSFUN_HEAVYWEIGHT_TEST(flags); }
|
||||
unsigned minArgs() const { return FUN_MINARGS(this); }
|
||||
bool optimizedClosure() const { return FUN_KIND(this) > JSFUN_INTERPRETED; }
|
||||
bool needsWrapper() const { return FUN_NULL_CLOSURE(this) && u.i.skipmin != 0; }
|
||||
bool isInterpreted() const { return FUN_INTERPRETED(this); }
|
||||
bool isFastNative() const { return !!(flags & JSFUN_FAST_NATIVE); }
|
||||
bool isFastConstructor() const { return !!(flags & JSFUN_FAST_NATIVE_CTOR); }
|
||||
bool isHeavyweight() const { return JSFUN_HEAVYWEIGHT_TEST(flags); }
|
||||
unsigned minArgs() const { return FUN_MINARGS(this); }
|
||||
|
||||
uintN countVars() const {
|
||||
JS_ASSERT(FUN_INTERPRETED(this));
|
||||
|
@ -294,7 +294,12 @@ namespace js {
|
||||
bool
|
||||
ComputeThisFromArgv(JSContext *cx, Value *argv)
|
||||
{
|
||||
JS_ASSERT(!argv[-1].isMagic()); // check for SynthesizeFrame poisoning
|
||||
/*
|
||||
* Check for SynthesizeFrame poisoning and fast constructors which
|
||||
* didn't check their vp properly.
|
||||
*/
|
||||
JS_ASSERT(!argv[-1].isMagic());
|
||||
|
||||
if (argv[-1].isNull())
|
||||
return ComputeGlobalThis(cx, argv);
|
||||
|
||||
@ -1195,6 +1200,23 @@ InvokeConstructor(JSContext *cx, const InvokeArgsGuard &args)
|
||||
|
||||
JSObject *obj2 = &vp->toObject();
|
||||
|
||||
/*
|
||||
* Call fast constructors without making the object first.
|
||||
* The native will be able to make the right new object faster.
|
||||
*/
|
||||
if (obj2->isFunction()) {
|
||||
JSFunction *fun = (JSFunction *) obj2->getPrivate();
|
||||
if (fun->isFastConstructor()) {
|
||||
vp[1].setMagic(JS_FAST_CONSTRUCTOR);
|
||||
|
||||
FastNative fn = (FastNative)fun->u.n.native;
|
||||
if (!fn(cx, args.getArgc(), vp))
|
||||
return JS_FALSE;
|
||||
JS_ASSERT(!vp->isPrimitive());
|
||||
return JS_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the constructor prototype object for this function.
|
||||
* Use the nominal 'this' parameter slot, vp[1], as a local
|
||||
|
@ -106,7 +106,8 @@ JS_FRIEND_DATA(const JSObjectMap) JSObjectMap::sharedNonNative(JSObjectMap::SHAP
|
||||
|
||||
Class js_ObjectClass = {
|
||||
js_Object_str,
|
||||
JSCLASS_HAS_CACHED_PROTO(JSProto_Object),
|
||||
JSCLASS_HAS_CACHED_PROTO(JSProto_Object) |
|
||||
JSCLASS_FAST_CONSTRUCTOR,
|
||||
PropertyStub, /* addProperty */
|
||||
PropertyStub, /* delProperty */
|
||||
PropertyStub, /* getProperty */
|
||||
@ -2554,25 +2555,25 @@ static JSFunctionSpec object_static_methods[] = {
|
||||
};
|
||||
|
||||
JSBool
|
||||
js_Object(JSContext *cx, JSObject *obj, uintN argc, Value *argv, Value *rval)
|
||||
js_Object(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
JSObject *obj;
|
||||
if (argc == 0) {
|
||||
/* Trigger logic below to construct a blank object. */
|
||||
obj = NULL;
|
||||
} else {
|
||||
/* If argv[0] is null or undefined, obj comes back null. */
|
||||
if (!js_ValueToObjectOrNull(cx, argv[0], &obj))
|
||||
if (!js_ValueToObjectOrNull(cx, vp[2], &obj))
|
||||
return JS_FALSE;
|
||||
}
|
||||
if (!obj) {
|
||||
JS_ASSERT(!argc || argv[0].isNull() || argv[0].isUndefined());
|
||||
if (JS_IsConstructing(cx))
|
||||
return JS_TRUE;
|
||||
/* Make an object whether this was called with 'new' or not. */
|
||||
JS_ASSERT(!argc || vp[2].isNull() || vp[2].isUndefined());
|
||||
obj = NewBuiltinClassInstance(cx, &js_ObjectClass);
|
||||
if (!obj)
|
||||
return JS_FALSE;
|
||||
}
|
||||
rval->setObject(*obj);
|
||||
vp->setObject(*obj);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
@ -3254,7 +3255,7 @@ Class js_BlockClass = {
|
||||
JSObject *
|
||||
js_InitObjectClass(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
JSObject *proto = js_InitClass(cx, obj, NULL, &js_ObjectClass, js_Object, 1,
|
||||
JSObject *proto = js_InitClass(cx, obj, NULL, &js_ObjectClass, (Native) js_Object, 1,
|
||||
object_props, object_methods, NULL, object_static_methods);
|
||||
if (!proto)
|
||||
return NULL;
|
||||
@ -3403,7 +3404,11 @@ js_InitClass(JSContext *cx, JSObject *obj, JSObject *parent_proto,
|
||||
|
||||
ctor = proto;
|
||||
} else {
|
||||
fun = js_NewFunction(cx, NULL, constructor, nargs, 0, obj, atom);
|
||||
uint16 flags = 0;
|
||||
if (clasp->flags & JSCLASS_FAST_CONSTRUCTOR)
|
||||
flags |= JSFUN_FAST_NATIVE | JSFUN_FAST_NATIVE_CTOR;
|
||||
|
||||
fun = js_NewFunction(cx, NULL, constructor, nargs, flags, obj, atom);
|
||||
if (!fun)
|
||||
goto bad;
|
||||
|
||||
|
@ -1332,7 +1332,7 @@ js_InferFlags(JSContext *cx, uintN defaultFlags);
|
||||
|
||||
/* Object constructor native. Exposed only so the JIT can know its address. */
|
||||
JSBool
|
||||
js_Object(JSContext *cx, JSObject *obj, uintN argc, js::Value *argv, js::Value *rval);
|
||||
js_Object(JSContext *cx, uintN argc, js::Value *vp);
|
||||
|
||||
|
||||
namespace js {
|
||||
|
@ -805,7 +805,8 @@ str_resolve(JSContext *cx, JSObject *obj, jsid id, uintN flags,
|
||||
Class js_StringClass = {
|
||||
js_String_str,
|
||||
JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_NEW_RESOLVE |
|
||||
JSCLASS_HAS_CACHED_PROTO(JSProto_String),
|
||||
JSCLASS_HAS_CACHED_PROTO(JSProto_String) |
|
||||
JSCLASS_FAST_CONSTRUCTOR,
|
||||
PropertyStub, /* addProperty */
|
||||
PropertyStub, /* delProperty */
|
||||
str_getProperty,
|
||||
@ -3123,23 +3124,28 @@ const char JSString::deflatedUnitStringTable[] = {
|
||||
#undef U8
|
||||
|
||||
JSBool
|
||||
js_String(JSContext *cx, JSObject *obj, uintN argc, Value *argv, Value *rval)
|
||||
js_String(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
JSString *str;
|
||||
|
||||
if (argc > 0) {
|
||||
str = js_ValueToString(cx, argv[0]);
|
||||
str = js_ValueToString(cx, vp[2]);
|
||||
if (!str)
|
||||
return JS_FALSE;
|
||||
argv[0].setString(str);
|
||||
vp[2].setString(str);
|
||||
} else {
|
||||
str = cx->runtime->emptyString;
|
||||
}
|
||||
if (!JS_IsConstructing(cx)) {
|
||||
rval->setString(str);
|
||||
return JS_TRUE;
|
||||
|
||||
if (vp[1].isMagic(JS_FAST_CONSTRUCTOR)) {
|
||||
JSObject *obj = NewBuiltinClassInstance(cx, &js_StringClass);
|
||||
if (!obj)
|
||||
return JS_FALSE;
|
||||
obj->setPrimitiveThis(StringValue(str));
|
||||
vp->setObject(*obj);
|
||||
} else {
|
||||
vp->setString(str);
|
||||
}
|
||||
obj->setPrimitiveThis(StringValue(str));
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
@ -3229,7 +3235,7 @@ js_InitStringClass(JSContext *cx, JSObject *obj)
|
||||
if (!JS_DefineFunctions(cx, obj, string_functions))
|
||||
return NULL;
|
||||
|
||||
proto = js_InitClass(cx, obj, NULL, &js_StringClass, js_String, 1,
|
||||
proto = js_InitClass(cx, obj, NULL, &js_StringClass, (Native) js_String, 1,
|
||||
NULL, string_methods,
|
||||
NULL, string_static_methods);
|
||||
if (!proto)
|
||||
|
@ -1159,7 +1159,7 @@ js_PutEscapedStringImpl(char *buffer, size_t bufferSize, FILE *fp,
|
||||
JSString *str, uint32 quote);
|
||||
|
||||
extern JSBool
|
||||
js_String(JSContext *cx, JSObject *obj, uintN argc, js::Value *argv, js::Value *rval);
|
||||
js_String(JSContext *cx, uintN argc, js::Value *vp);
|
||||
|
||||
namespace js {
|
||||
|
||||
|
@ -11572,22 +11572,20 @@ TraceRecorder::functionCall(uintN argc, JSOp mode)
|
||||
return interpretedFunctionCall(fval, fun, argc, mode == JSOP_NEW);
|
||||
}
|
||||
|
||||
if (FUN_SLOW_NATIVE(fun)) {
|
||||
Native native = fun->u.n.native;
|
||||
Value* argv = &tval + 1;
|
||||
if (native == js_Array)
|
||||
return newArray(&fval.toObject(), argc, argv, &fval);
|
||||
if (native == js_String && argc == 1) {
|
||||
if (mode == JSOP_NEW)
|
||||
return newString(&fval.toObject(), 1, argv, &fval);
|
||||
if (!argv[0].isPrimitive()) {
|
||||
CHECK_STATUS(guardNativeConversion(argv[0]));
|
||||
return callImacro(call_imacros.String);
|
||||
}
|
||||
set(&fval, stringify(argv[0]));
|
||||
pendingSpecializedNative = IGNORE_NATIVE_CALL_COMPLETE_CALLBACK;
|
||||
return RECORD_CONTINUE;
|
||||
FastNative native = FUN_FAST_NATIVE(fun);
|
||||
Value* argv = &tval + 1;
|
||||
if (native == js_Array)
|
||||
return newArray(&fval.toObject(), argc, argv, &fval);
|
||||
if (native == js_String && argc == 1) {
|
||||
if (mode == JSOP_NEW)
|
||||
return newString(&fval.toObject(), 1, argv, &fval);
|
||||
if (!argv[0].isPrimitive()) {
|
||||
CHECK_STATUS(guardNativeConversion(argv[0]));
|
||||
return callImacro(call_imacros.String);
|
||||
}
|
||||
set(&fval, stringify(argv[0]));
|
||||
pendingSpecializedNative = IGNORE_NATIVE_CALL_COMPLETE_CALLBACK;
|
||||
return RECORD_CONTINUE;
|
||||
}
|
||||
|
||||
return callNative(argc, mode);
|
||||
|
@ -260,6 +260,7 @@ typedef enum JSWhyMagic
|
||||
* enumerated like a native object. */
|
||||
JS_NO_ITER_VALUE, /* there is not a pending iterator value */
|
||||
JS_GENERATOR_CLOSING, /* exception value thrown when closing a generator */
|
||||
JS_FAST_CONSTRUCTOR, /* 'this' value for fast natives invoked with 'new' */
|
||||
JS_NO_CONSTANT, /* compiler sentinel value */
|
||||
JS_THIS_POISON, /* used in debug builds to catch tracing errors */
|
||||
JS_GENERIC_MAGIC /* for local use */
|
||||
|
@ -418,6 +418,17 @@ stubs::SlowNew(VMFrame &f, uint32 argc)
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (fun->isFastConstructor()) {
|
||||
vp[1].setMagic(JS_FAST_CONSTRUCTOR);
|
||||
|
||||
FastNative fn = (FastNative)fun->u.n.native;
|
||||
if (!fn(cx, argc, vp))
|
||||
THROWV(NULL);
|
||||
JS_ASSERT(!vp->isPrimitive());
|
||||
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!InvokeConstructor(cx, InvokeArgsGuard(vp, argc)))
|
||||
|
Loading…
Reference in New Issue
Block a user