зеркало из https://github.com/mozilla/gecko-dev.git
Bug 851763 - part 1: add support for wrapping self-hosted functions instead of cloning them. r=jwalden
--HG-- extra : rebase_source : 12bbbd1bc17bedc97a9da6189dd5c1c0773e54c1
This commit is contained in:
Родитель
ebb97727c3
Коммит
52ccc5c1e9
|
@ -70,16 +70,15 @@ var std_WeakMap_set = WeakMap.prototype.set;
|
|||
|
||||
|
||||
/* Spec: ECMAScript Language Specification, 5.1 edition, 8.8 */
|
||||
function List() {
|
||||
if (List.prototype === undefined) {
|
||||
var proto = std_Object_create(null);
|
||||
proto.indexOf = std_Array_indexOf;
|
||||
proto.join = std_Array_join;
|
||||
proto.push = std_Array_push;
|
||||
proto.slice = std_Array_slice;
|
||||
proto.sort = std_Array_sort;
|
||||
List.prototype = proto;
|
||||
}
|
||||
function List() {}
|
||||
{
|
||||
let ListProto = std_Object_create(null);
|
||||
ListProto.indexOf = std_Array_indexOf;
|
||||
ListProto.join = std_Array_join;
|
||||
ListProto.push = std_Array_push;
|
||||
ListProto.slice = std_Array_slice;
|
||||
ListProto.sort = std_Array_sort;
|
||||
List.prototype = ListProto;
|
||||
}
|
||||
MakeConstructible(List);
|
||||
|
||||
|
|
|
@ -5051,21 +5051,31 @@ JS_DefineFunctions(JSContext *cx, JSObject *objArg, const JSFunctionSpec *fs)
|
|||
if (cx->runtime->isSelfHostingGlobal(cx->global()))
|
||||
continue;
|
||||
|
||||
RootedFunction fun(cx, DefineFunction(cx, obj, id, /* native = */ NULL, fs->nargs, 0,
|
||||
JSFunction::ExtendedFinalizeKind, SingletonObject));
|
||||
if (!fun)
|
||||
return JS_FALSE;
|
||||
fun->setIsSelfHostedBuiltin();
|
||||
fun->setExtendedSlot(0, PrivateValue(const_cast<JSFunctionSpec*>(fs)));
|
||||
RootedAtom shAtom(cx, Atomize(cx, fs->selfHostedName, strlen(fs->selfHostedName)));
|
||||
if (!shAtom)
|
||||
return JS_FALSE;
|
||||
RootedObject holder(cx, cx->global()->intrinsicsHolder());
|
||||
if (!JS_DefinePropertyById(cx,holder, AtomToId(shAtom),
|
||||
ObjectValue(*fun), NULL, NULL, 0))
|
||||
{
|
||||
RootedPropertyName shName(cx, shAtom->asPropertyName());
|
||||
RootedValue funVal(cx);
|
||||
if (!cx->runtime->maybeWrappedSelfHostedFunction(cx, shName, &funVal))
|
||||
return JS_FALSE;
|
||||
if (!funVal.isUndefined()) {
|
||||
if (!JSObject::defineProperty(cx, obj, atom->asPropertyName(), funVal,
|
||||
NULL, NULL, flags & ~JSFUN_FLAGS_MASK))
|
||||
{
|
||||
return JS_FALSE;
|
||||
}
|
||||
} else {
|
||||
RawFunction fun = DefineFunction(cx, obj, id, /* native = */ NULL, fs->nargs, 0,
|
||||
JSFunction::ExtendedFinalizeKind, SingletonObject);
|
||||
if (!fun)
|
||||
return JS_FALSE;
|
||||
fun->setIsSelfHostedBuiltin();
|
||||
fun->setExtendedSlot(0, PrivateValue(const_cast<JSFunctionSpec*>(fs)));
|
||||
funVal.setObject(*fun);
|
||||
}
|
||||
RootedObject holder(cx, cx->global()->intrinsicsHolder());
|
||||
if (!JSObject::defineProperty(cx, holder, shName, funVal))
|
||||
return JS_FALSE;
|
||||
} else {
|
||||
JSFunction *fun = DefineFunction(cx, obj, id, fs->call.op, fs->nargs, flags);
|
||||
if (!fun)
|
||||
|
|
|
@ -776,6 +776,8 @@ struct JSRuntime : private JS::shadow::Runtime,
|
|||
js::Handle<JSFunction*> targetFun);
|
||||
bool cloneSelfHostedValue(JSContext *cx, js::Handle<js::PropertyName*> name,
|
||||
js::MutableHandleValue vp);
|
||||
bool maybeWrappedSelfHostedFunction(JSContext *cx, js::Handle<js::PropertyName*> name,
|
||||
js::MutableHandleValue funVal);
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Locale information
|
||||
|
|
|
@ -44,6 +44,7 @@ class JSFunction : public JSObject
|
|||
HAS_DEFAULTS = 0x0800, /* function has at least one default parameter */
|
||||
INTERPRETED_LAZY = 0x1000, /* function is interpreted but doesn't have a script yet */
|
||||
ARROW = 0x2000, /* ES6 '(args) => body' syntax */
|
||||
SH_WRAPPABLE = 0x4000, /* self-hosted function is wrappable, doesn't need to be cloned */
|
||||
|
||||
/* Derived Flags values for convenience: */
|
||||
NATIVE_FUN = 0,
|
||||
|
@ -100,6 +101,10 @@ class JSFunction : public JSObject
|
|||
bool isSelfHostedConstructor() const { return flags & SELF_HOSTED_CTOR; }
|
||||
bool hasRest() const { return flags & HAS_REST; }
|
||||
bool hasDefaults() const { return flags & HAS_DEFAULTS; }
|
||||
bool isWrappable() const {
|
||||
JS_ASSERT_IF(flags & SH_WRAPPABLE, isSelfHostedBuiltin());
|
||||
return flags & SH_WRAPPABLE;
|
||||
}
|
||||
|
||||
// Arrow functions are a little weird.
|
||||
//
|
||||
|
@ -155,6 +160,12 @@ class JSFunction : public JSObject
|
|||
flags |= SELF_HOSTED_CTOR;
|
||||
}
|
||||
|
||||
void makeWrappable() {
|
||||
JS_ASSERT(isSelfHostedBuiltin());
|
||||
JS_ASSERT(!isWrappable());
|
||||
flags |= SH_WRAPPABLE;
|
||||
}
|
||||
|
||||
void setIsFunctionPrototype() {
|
||||
JS_ASSERT(!isFunctionPrototype());
|
||||
flags |= IS_FUN_PROTO;
|
||||
|
|
|
@ -2489,7 +2489,7 @@ BEGIN_CASE(JSOP_CALLINTRINSIC)
|
|||
{
|
||||
RootedValue &rval = rootValue0;
|
||||
|
||||
if (!GetIntrinsicOperation(cx, script, regs.pc, &rval))
|
||||
if (!GetIntrinsicOperation(cx, regs.pc, &rval))
|
||||
goto error;
|
||||
|
||||
PUSH_COPY(rval);
|
||||
|
|
|
@ -418,10 +418,9 @@ FetchNameNoGC(JSObject *pobj, Shape *shape, MutableHandleValue vp)
|
|||
}
|
||||
|
||||
inline bool
|
||||
GetIntrinsicOperation(JSContext *cx, JSScript *script, jsbytecode *pc, MutableHandleValue vp)
|
||||
GetIntrinsicOperation(JSContext *cx, jsbytecode *pc, MutableHandleValue vp)
|
||||
{
|
||||
JSOp op = JSOp(*pc);
|
||||
RootedPropertyName name(cx, GetNameFromBytecode(cx, script, pc, op));
|
||||
RootedPropertyName name(cx, cx->stack.currentScript()->getName(pc));
|
||||
return cx->global()->getIntrinsicValue(cx, name, vp);
|
||||
}
|
||||
|
||||
|
|
|
@ -142,6 +142,19 @@ intrinsic_MakeConstructible(JSContext *cx, unsigned argc, Value *vp)
|
|||
JS_ASSERT(args[0].isObject());
|
||||
JS_ASSERT(args[0].toObject().isFunction());
|
||||
args[0].toObject().toFunction()->setIsSelfHostedConstructor();
|
||||
args.rval().setUndefined();
|
||||
return true;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
intrinsic_MakeWrappable(JSContext *cx, unsigned argc, Value *vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
JS_ASSERT(args.length() >= 1);
|
||||
JS_ASSERT(args[0].isObject());
|
||||
JS_ASSERT(args[0].toObject().isFunction());
|
||||
args[0].toObject().toFunction()->makeWrappable();
|
||||
args.rval().setUndefined();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -204,6 +217,7 @@ intrinsic_SetScriptHints(JSContext *cx, unsigned argc, Value *vp)
|
|||
if (ToBoolean(propv))
|
||||
funScript->shouldCloneAtCallsite = true;
|
||||
|
||||
args.rval().setUndefined();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -217,7 +231,6 @@ js::intrinsic_Dump(JSContext *cx, unsigned argc, Value *vp)
|
|||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
RootedValue val(cx, args[0]);
|
||||
js_DumpValue(val);
|
||||
fprintf(stderr, "\n");
|
||||
args.rval().setUndefined();
|
||||
return true;
|
||||
}
|
||||
|
@ -458,6 +471,7 @@ JSFunctionSpec intrinsic_functions[] = {
|
|||
JS_FN("AssertionFailed", intrinsic_AssertionFailed, 1,0),
|
||||
JS_FN("SetScriptHints", intrinsic_SetScriptHints, 2,0),
|
||||
JS_FN("MakeConstructible", intrinsic_MakeConstructible, 1,0),
|
||||
JS_FN("MakeWrappable", intrinsic_MakeWrappable, 1,0),
|
||||
JS_FN("DecompileArg", intrinsic_DecompileArg, 2,0),
|
||||
JS_FN("RuntimeDefaultLocale", intrinsic_RuntimeDefaultLocale, 0,0),
|
||||
|
||||
|
@ -515,6 +529,8 @@ JSRuntime::initSelfHosting(JSContext *cx)
|
|||
CompileOptions options(cx);
|
||||
options.setFileAndLine("self-hosted", 1);
|
||||
options.setSelfHostingMode(true);
|
||||
options.setSourcePolicy(CompileOptions::NO_SOURCE);
|
||||
options.setVersion(JSVERSION_LATEST);
|
||||
|
||||
/*
|
||||
* Set a temporary error reporter printing to stderr because it is too
|
||||
|
@ -606,8 +622,14 @@ CloneObject(JSContext *cx, HandleObject srcObj, CloneMemory &clonedObjects)
|
|||
return p->value;
|
||||
RootedObject clone(cx);
|
||||
if (srcObj->isFunction()) {
|
||||
RootedFunction fun(cx, srcObj->toFunction());
|
||||
clone = CloneFunctionObject(cx, fun, cx->global(), fun->getAllocKind());
|
||||
if (srcObj->toFunction()->isWrappable()) {
|
||||
clone = srcObj;
|
||||
if (!cx->compartment->wrap(cx, clone.address()))
|
||||
return NULL;
|
||||
} else {
|
||||
RootedFunction fun(cx, srcObj->toFunction());
|
||||
clone = CloneFunctionObject(cx, fun, cx->global(), fun->getAllocKind());
|
||||
}
|
||||
} else if (srcObj->isRegExp()) {
|
||||
RegExpObject &reobj = srcObj->asRegExp();
|
||||
RootedAtom source(cx, reobj.getSource());
|
||||
|
@ -679,7 +701,7 @@ JSRuntime::cloneSelfHostedFunctionScript(JSContext *cx, Handle<PropertyName*> na
|
|||
return false;
|
||||
|
||||
RootedFunction sourceFun(cx, funVal.toObject().toFunction());
|
||||
Rooted<JSScript*> sourceScript(cx, sourceFun->nonLazyScript());
|
||||
RootedScript sourceScript(cx, sourceFun->nonLazyScript());
|
||||
JS_ASSERT(!sourceScript->enclosingStaticScope());
|
||||
RawScript cscript = CloneScript(cx, NullPtr(), targetFun, sourceScript);
|
||||
if (!cscript)
|
||||
|
@ -713,3 +735,23 @@ JSRuntime::cloneSelfHostedValue(JSContext *cx, Handle<PropertyName*> name, Mutab
|
|||
vp.set(val);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
JSRuntime::maybeWrappedSelfHostedFunction(JSContext *cx, Handle<PropertyName*> name,
|
||||
MutableHandleValue funVal)
|
||||
{
|
||||
RootedObject shg(cx, selfHostingGlobal_);
|
||||
RootedId id(cx, NameToId(name));
|
||||
if (!GetUnclonedValue(cx, shg, id, funVal))
|
||||
return false;
|
||||
|
||||
JS_ASSERT(funVal.isObject());
|
||||
JS_ASSERT(funVal.toObject().isCallable());
|
||||
|
||||
if (!funVal.toObject().toFunction()->isWrappable()) {
|
||||
funVal.setUndefined();
|
||||
return true;
|
||||
}
|
||||
|
||||
return cx->compartment->wrap(cx, funVal);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче