Bug 1270331 - Pass JS_IS_CONSTRUCTING as |this| to constructing functions from bytecode. (r=Waldo, r=jandem)

This commit is contained in:
Eric Faust 2016-06-27 15:21:13 -07:00
Родитель 2739ec5b28
Коммит f45a2ae8f5
11 изменённых файлов: 74 добавлений и 33 удалений

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

@ -7708,13 +7708,21 @@ BytecodeEmitter::emitCallOrNew(ParseNode* pn)
callop = false; /* trigger JSOP_UNDEFINED after */
break;
}
if (!callop) {
if (!emit1(JSOP_UNDEFINED))
return false;
}
bool isNewOp = pn->getOp() == JSOP_NEW || pn->getOp() == JSOP_SPREADNEW ||
pn->getOp() == JSOP_SUPERCALL || pn->getOp() == JSOP_SPREADSUPERCALL;;
pn->getOp() == JSOP_SUPERCALL || pn->getOp() == JSOP_SPREADSUPERCALL;
// Emit room for |this|.
if (!callop) {
if (isNewOp) {
if (!emit1(JSOP_IS_CONSTRUCTING))
return false;
} else {
if (!emit1(JSOP_UNDEFINED))
return false;
}
}
/*
* Emit code for each argument in order, then emit the JSOP_*CALL or

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

@ -4328,6 +4328,13 @@ BaselineCompiler::emit_JSOP_DEBUGCHECKSELFHOSTED()
}
bool
BaselineCompiler::emit_JSOP_IS_CONSTRUCTING()
{
frame.push(MagicValue(JS_IS_CONSTRUCTING));
return true;
}
bool
BaselineCompiler::emit_JSOP_JUMPTARGET()
{

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

@ -224,7 +224,8 @@ namespace jit {
_(JSOP_INITHIDDENELEM_SETTER) \
_(JSOP_CHECKOBJCOERCIBLE) \
_(JSOP_DEBUGCHECKSELFHOSTED) \
_(JSOP_JUMPTARGET)
_(JSOP_JUMPTARGET) \
_(JSOP_IS_CONSTRUCTING)
class BaselineCompiler : public BaselineCompilerSpecific
{

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

@ -6972,12 +6972,6 @@ ICCall_Native::Compiler::generateStubCode(MacroAssembler& masm)
else
pushCallArguments(masm, regs, argcReg, /* isJitCall = */ false, isConstructing_);
if (isConstructing_) {
// Stack looks like: [ ..., Arg0Val, ThisVal, CalleeVal ]
// Replace ThisVal with MagicValue(JS_IS_CONSTRUCTING)
masm.storeValue(MagicValue(JS_IS_CONSTRUCTING), Address(masm.getStackPointer(), sizeof(Value)));
}
// Native functions have the signature:
//
@ -7070,12 +7064,6 @@ ICCall_ClassHook::Compiler::generateStubCode(MacroAssembler& masm)
pushCallArguments(masm, regs, argcReg, /* isJitCall = */ false, isConstructing_);
regs.take(scratch);
if (isConstructing_) {
// Stack looks like: [ ..., Arg0Val, ThisVal, CalleeVal ]
// Replace ThisVal with MagicValue(JS_IS_CONSTRUCTING)
masm.storeValue(MagicValue(JS_IS_CONSTRUCTING), Address(masm.getStackPointer(), sizeof(Value)));
}
masm.checkStackAlignment();
// Native functions have the signature:

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

@ -2791,6 +2791,7 @@ IsResumableMIRType(MIRType type)
case MIRType::MagicOptimizedArguments:
case MIRType::MagicOptimizedOut:
case MIRType::MagicUninitializedLexical:
case MIRType::MagicIsConstructing:
case MIRType::Value:
case MIRType::Int32x4:
case MIRType::Int16x8:
@ -2802,7 +2803,6 @@ IsResumableMIRType(MIRType type)
return true;
case MIRType::MagicHole:
case MIRType::MagicIsConstructing:
case MIRType::ObjectOrNull:
case MIRType::None:
case MIRType::Slots:

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

@ -2160,6 +2160,9 @@ IonBuilder::inspectOpcode(JSOp op)
return true;
}
case JSOP_IS_CONSTRUCTING:
pushConstant(MagicValue(JS_IS_CONSTRUCTING));
return true;
#ifdef DEBUG
case JSOP_PUSHBLOCKSCOPE:

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

@ -485,13 +485,28 @@ CodeGeneratorShared::encodeAllocation(LSnapshot* snapshot, MDefinition* mir,
case MIRType::MagicOptimizedArguments:
case MIRType::MagicOptimizedOut:
case MIRType::MagicUninitializedLexical:
case MIRType::MagicIsConstructing:
{
uint32_t index;
Value v = MagicValue(type == MIRType::MagicOptimizedArguments
? JS_OPTIMIZED_ARGUMENTS
: (type == MIRType::MagicOptimizedOut
? JS_OPTIMIZED_OUT
: JS_UNINITIALIZED_LEXICAL));
JSWhyMagic why = JS_GENERIC_MAGIC;
switch (type) {
case MIRType::MagicOptimizedArguments:
why = JS_OPTIMIZED_ARGUMENTS;
break;
case MIRType::MagicOptimizedOut:
why = JS_OPTIMIZED_OUT;
break;
case MIRType::MagicUninitializedLexical:
why = JS_UNINITIALIZED_LEXICAL;
break;
case MIRType::MagicIsConstructing:
why = JS_IS_CONSTRUCTING;
break;
default:
MOZ_CRASH("Invalid Magic MIRType");
}
Value v = MagicValue(why);
masm.propagateOOM(graph.addConstantToPool(v, &index));
alloc = RValueAllocation::ConstantPool(index);
break;

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

@ -321,6 +321,7 @@ RunState::maybeCreateThisForConstructor(JSContext* cx)
MOZ_ASSERT(callee->as<JSFunction>().isClassConstructor());
invoke.args().setThis(MagicValue(JS_UNINITIALIZED_LEXICAL));
} else {
MOZ_ASSERT(invoke.args().thisv().isMagic(JS_IS_CONSTRUCTING));
RootedObject newTarget(cx, &invoke.args().newTarget().toObject());
NewObjectKind newKind = invoke.createSingleton() ? SingletonObject : GenericObject;
JSObject* obj = CreateThisForFunction(cx, callee, newTarget, newKind);
@ -533,6 +534,8 @@ InternalConstruct(JSContext* cx, const AnyConstructArgs& args)
MOZ_ASSERT(IsConstructor(args.CallArgs::newTarget()),
"provided new.target value must be a constructor");
MOZ_ASSERT(args.thisv().isMagic(JS_IS_CONSTRUCTING) || args.thisv().isObject());
JSObject& callee = args.callee();
if (callee.is<JSFunction>()) {
RootedFunction fun(cx, &callee.as<JSFunction>());
@ -576,7 +579,6 @@ js::ConstructFromStack(JSContext* cx, const CallArgs& args)
if (!StackCheckIsConstructorCalleeNewTarget(cx, args.calleev(), args.newTarget()))
return false;
args.setThis(MagicValue(JS_IS_CONSTRUCTING));
return InternalConstruct(cx, static_cast<const AnyConstructArgs&>(args));
}
@ -584,9 +586,10 @@ bool
js::Construct(JSContext* cx, HandleValue fval, const AnyConstructArgs& args, HandleValue newTarget,
MutableHandleObject objp)
{
MOZ_ASSERT(args.thisv().isMagic(JS_IS_CONSTRUCTING));
// Explicitly qualify to bypass AnyConstructArgs's deliberate shadowing.
args.CallArgs::setCallee(fval);
args.CallArgs::setThis(MagicValue(JS_IS_CONSTRUCTING));
args.CallArgs::newTarget().set(newTarget);
if (!InternalConstruct(cx, args))
@ -1265,8 +1268,7 @@ HandleError(JSContext* cx, InterpreterRegs& regs)
#define PUSH_STRING(s) do { REGS.sp++->setString(s); assertSameCompartmentDebugOnly(cx, REGS.sp[-1]); } while (0)
#define PUSH_OBJECT(obj) do { REGS.sp++->setObject(obj); assertSameCompartmentDebugOnly(cx, REGS.sp[-1]); } while (0)
#define PUSH_OBJECT_OR_NULL(obj) do { REGS.sp++->setObjectOrNull(obj); assertSameCompartmentDebugOnly(cx, REGS.sp[-1]); } while (0)
#define PUSH_HOLE() REGS.sp++->setMagic(JS_ELEMENTS_HOLE)
#define PUSH_UNINITIALIZED() REGS.sp++->setMagic(JS_UNINITIALIZED_LEXICAL)
#define PUSH_MAGIC(magic) REGS.sp++->setMagic(magic)
#define POP_COPY_TO(v) (v) = *--REGS.sp
#define POP_RETURN_VALUE() REGS.fp()->setReturnValue(*--REGS.sp)
@ -1824,7 +1826,6 @@ CASE(EnableInterruptsPseudoOpcode)
CASE(JSOP_NOP)
CASE(JSOP_NOP_DESTRUCTURING)
CASE(JSOP_UNUSED14)
CASE(JSOP_UNUSED65)
CASE(JSOP_UNUSED149)
CASE(JSOP_UNUSED179)
CASE(JSOP_UNUSED180)
@ -3295,7 +3296,7 @@ CASE(JSOP_INITGLEXICAL)
END_CASE(JSOP_INITGLEXICAL)
CASE(JSOP_UNINITIALIZED)
PUSH_UNINITIALIZED();
PUSH_MAGIC(JS_UNINITIALIZED_LEXICAL);
END_CASE(JSOP_UNINITIALIZED)
CASE(JSOP_GETARG)
@ -3470,7 +3471,7 @@ CASE(JSOP_INITHIDDENELEM_SETTER)
END_CASE(JSOP_INITELEM_GETTER)
CASE(JSOP_HOLE)
PUSH_HOLE();
PUSH_MAGIC(JS_ELEMENTS_HOLE);
END_CASE(JSOP_HOLE)
CASE(JSOP_NEWINIT)
@ -4026,6 +4027,10 @@ CASE(JSOP_DEBUGCHECKSELFHOSTED)
}
END_CASE(JSOP_DEBUGCHECKSELFHOSTED)
CASE(JSOP_IS_CONSTRUCTING)
PUSH_MAGIC(JS_IS_CONSTRUCTING);
END_CASE(JSOP_IS_CONSTRUCTING)
DEFAULT()
{
char numBuf[12];

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

@ -603,7 +603,14 @@
* Stack: => null
*/ \
macro(JSOP_NULL, 64, js_null_str, js_null_str, 1, 0, 1, JOF_BYTE) \
macro(JSOP_UNUSED65, 65, "unused65", NULL, 1, 0, 1, JOF_BYTE) \
/*
* Pushes 'JS_IS_CONSTRUCTING'
* Category: Literals
* Type: Constants
* Operands:
* Stack: => JS_IS_CONSTRUCTING
*/ \
macro(JSOP_IS_CONSTRUCTING, 65, "is-constructing", NULL, 1, 0, 1, JOF_BYTE) \
/*
* Pushes boolean value onto the stack.
* Category: Literals

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

@ -224,7 +224,10 @@ InterpreterFrame::prologue(JSContext* cx)
} else if (script->isDerivedClassConstructor()) {
MOZ_ASSERT(callee().isClassConstructor());
thisArgument() = MagicValue(JS_UNINITIALIZED_LEXICAL);
} else if (thisArgument().isPrimitive()) {
} else if (thisArgument().isObject()) {
// Nothing to do. Correctly set.
} else {
MOZ_ASSERT(thisArgument().isMagic(JS_IS_CONSTRUCTING));
RootedObject callee(cx, &this->callee());
RootedObject newTarget(cx, &this->newTarget().toObject());
JSObject* obj = CreateThisForFunction(cx, callee, newTarget,

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

@ -966,6 +966,8 @@ class GenericArgsBase
*static_cast<JS::CallArgs*>(this) = CallArgsFromVp(argc, v_.begin());
this->constructing_ = Construct;
if (Construct)
this->CallArgs::setThis(MagicValue(JS_IS_CONSTRUCTING));
return true;
}
};
@ -981,6 +983,8 @@ class FixedArgsBase
explicit FixedArgsBase(JSContext* cx) : v_(cx) {
*static_cast<JS::CallArgs*>(this) = CallArgsFromVp(N, v_.begin());
this->constructing_ = Construct;
if (Construct)
this->CallArgs::setThis(MagicValue(JS_IS_CONSTRUCTING));
}
};