зеркало из https://github.com/mozilla/gecko-dev.git
Bug 988993 - Ion-compile scripts with arrow functions. r=bhackett
This commit is contained in:
Родитель
1508b14577
Коммит
f9f45af324
|
@ -156,6 +156,7 @@ BytecodeAnalysis::init(TempAllocator &alloc, GSNCache &gsn)
|
|||
case JSOP_CALLALIASEDVAR:
|
||||
case JSOP_SETALIASEDVAR:
|
||||
case JSOP_LAMBDA:
|
||||
case JSOP_LAMBDA_ARROW:
|
||||
case JSOP_DEFFUN:
|
||||
case JSOP_DEFVAR:
|
||||
case JSOP_DEFCONST:
|
||||
|
|
|
@ -941,8 +941,7 @@ CodeGenerator::visitStringReplace(LStringReplace *lir)
|
|||
|
||||
|
||||
typedef JSObject *(*LambdaFn)(JSContext *, HandleFunction, HandleObject);
|
||||
static const VMFunction LambdaInfo =
|
||||
FunctionInfo<LambdaFn>(js::Lambda);
|
||||
static const VMFunction LambdaInfo = FunctionInfo<LambdaFn>(js::Lambda);
|
||||
|
||||
bool
|
||||
CodeGenerator::visitLambdaForSingleton(LLambdaForSingleton *lir)
|
||||
|
@ -976,10 +975,53 @@ CodeGenerator::visitLambda(LLambda *lir)
|
|||
return true;
|
||||
}
|
||||
|
||||
typedef JSObject *(*LambdaArrowFn)(JSContext *, HandleFunction, HandleObject, HandleValue);
|
||||
static const VMFunction LambdaArrowInfo = FunctionInfo<LambdaArrowFn>(js::LambdaArrow);
|
||||
|
||||
bool
|
||||
CodeGenerator::visitLambdaArrow(LLambdaArrow *lir)
|
||||
{
|
||||
Register scopeChain = ToRegister(lir->scopeChain());
|
||||
ValueOperand thisv = ToValue(lir, LLambdaArrow::ThisValue);
|
||||
Register output = ToRegister(lir->output());
|
||||
Register tempReg = ToRegister(lir->temp());
|
||||
const LambdaFunctionInfo &info = lir->mir()->info();
|
||||
|
||||
OutOfLineCode *ool = oolCallVM(LambdaArrowInfo, lir,
|
||||
(ArgList(), ImmGCPtr(info.fun), scopeChain, thisv),
|
||||
StoreRegisterTo(output));
|
||||
if (!ool)
|
||||
return false;
|
||||
|
||||
MOZ_ASSERT(!info.useNewTypeForClone);
|
||||
|
||||
if (info.singletonType) {
|
||||
// If the function has a singleton type, this instruction will only be
|
||||
// executed once so we don't bother inlining it.
|
||||
masm.jump(ool->entry());
|
||||
masm.bind(ool->rejoin());
|
||||
return true;
|
||||
}
|
||||
|
||||
masm.newGCThing(output, tempReg, info.fun, ool->entry(), gc::DefaultHeap);
|
||||
masm.initGCThing(output, tempReg, info.fun);
|
||||
|
||||
emitLambdaInit(output, scopeChain, info);
|
||||
|
||||
// Store the lexical |this| value.
|
||||
MOZ_ASSERT(info.flags & JSFunction::EXTENDED);
|
||||
masm.storeValue(thisv, Address(output, FunctionExtended::offsetOfArrowThisSlot()));
|
||||
|
||||
masm.bind(ool->rejoin());
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
CodeGenerator::emitLambdaInit(Register output, Register scopeChain,
|
||||
const LambdaFunctionInfo &info)
|
||||
{
|
||||
MOZ_ASSERT(!!(info.flags & JSFunction::ARROW) == !!(info.flags & JSFunction::EXTENDED));
|
||||
|
||||
// Initialize nargs and flags. We do this with a single uint32 to avoid
|
||||
// 16-bit writes.
|
||||
union {
|
||||
|
@ -990,7 +1032,7 @@ CodeGenerator::emitLambdaInit(Register output, Register scopeChain,
|
|||
uint32_t word;
|
||||
} u;
|
||||
u.s.nargs = info.fun->nargs();
|
||||
u.s.flags = info.flags & ~JSFunction::EXTENDED;
|
||||
u.s.flags = info.flags;
|
||||
|
||||
JS_ASSERT(JSFunction::offsetOfFlags() == JSFunction::offsetOfNargs() + 2);
|
||||
masm.store32(Imm32(u.word), Address(output, JSFunction::offsetOfNargs()));
|
||||
|
|
|
@ -99,6 +99,7 @@ class CodeGenerator : public CodeGeneratorSpecific
|
|||
bool visitRegExpReplace(LRegExpReplace *lir);
|
||||
bool visitStringReplace(LStringReplace *lir);
|
||||
bool visitLambda(LLambda *lir);
|
||||
bool visitLambdaArrow(LLambdaArrow *lir);
|
||||
bool visitLambdaForSingleton(LLambdaForSingleton *lir);
|
||||
bool visitLambdaPar(LLambdaPar *lir);
|
||||
bool visitPointer(LPointer *lir);
|
||||
|
|
|
@ -1711,6 +1711,9 @@ IonBuilder::inspectOpcode(JSOp op)
|
|||
case JSOP_LAMBDA:
|
||||
return jsop_lambda(info().getFunction(pc));
|
||||
|
||||
case JSOP_LAMBDA_ARROW:
|
||||
return jsop_lambda_arrow(info().getFunction(pc));
|
||||
|
||||
case JSOP_ITER:
|
||||
return jsop_iter(GET_INT8(pc));
|
||||
|
||||
|
@ -9420,9 +9423,9 @@ IonBuilder::jsop_object(JSObject *obj)
|
|||
bool
|
||||
IonBuilder::jsop_lambda(JSFunction *fun)
|
||||
{
|
||||
JS_ASSERT(analysis().usesScopeChain());
|
||||
if (fun->isArrow())
|
||||
return abort("bound arrow function");
|
||||
MOZ_ASSERT(analysis().usesScopeChain());
|
||||
MOZ_ASSERT(!fun->isArrow());
|
||||
|
||||
if (fun->isNative() && IsAsmJSModuleNative(fun->native()))
|
||||
return abort("asm.js module function");
|
||||
|
||||
|
@ -9433,6 +9436,23 @@ IonBuilder::jsop_lambda(JSFunction *fun)
|
|||
return resumeAfter(ins);
|
||||
}
|
||||
|
||||
bool
|
||||
IonBuilder::jsop_lambda_arrow(JSFunction *fun)
|
||||
{
|
||||
MOZ_ASSERT(analysis().usesScopeChain());
|
||||
MOZ_ASSERT(fun->isArrow());
|
||||
MOZ_ASSERT(!fun->isNative());
|
||||
|
||||
MDefinition *thisDef = current->pop();
|
||||
|
||||
MLambdaArrow *ins = MLambdaArrow::New(alloc(), constraints(), current->scopeChain(),
|
||||
thisDef, fun);
|
||||
current->add(ins);
|
||||
current->push(ins);
|
||||
|
||||
return resumeAfter(ins);
|
||||
}
|
||||
|
||||
bool
|
||||
IonBuilder::jsop_setarg(uint32_t arg)
|
||||
{
|
||||
|
|
|
@ -602,6 +602,7 @@ class IonBuilder : public MIRGenerator
|
|||
bool jsop_regexp(RegExpObject *reobj);
|
||||
bool jsop_object(JSObject *obj);
|
||||
bool jsop_lambda(JSFunction *fun);
|
||||
bool jsop_lambda_arrow(JSFunction *fun);
|
||||
bool jsop_this();
|
||||
bool jsop_typeof();
|
||||
bool jsop_toid();
|
||||
|
|
|
@ -3487,6 +3487,28 @@ class LLambda : public LInstructionHelper<1, 1, 1>
|
|||
}
|
||||
};
|
||||
|
||||
class LLambdaArrow : public LInstructionHelper<1, 1 + BOX_PIECES, 1>
|
||||
{
|
||||
public:
|
||||
LIR_HEADER(LambdaArrow)
|
||||
|
||||
static const size_t ThisValue = 1;
|
||||
|
||||
LLambdaArrow(const LAllocation &scopeChain, const LDefinition &temp) {
|
||||
setOperand(0, scopeChain);
|
||||
setTemp(0, temp);
|
||||
}
|
||||
const LAllocation *scopeChain() {
|
||||
return getOperand(0);
|
||||
}
|
||||
const LDefinition *temp() {
|
||||
return getTemp(0);
|
||||
}
|
||||
const MLambdaArrow *mir() const {
|
||||
return mir_->toLambdaArrow();
|
||||
}
|
||||
};
|
||||
|
||||
class LLambdaPar : public LInstructionHelper<1, 2, 2>
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -160,6 +160,7 @@
|
|||
_(RegExpReplace) \
|
||||
_(StringReplace) \
|
||||
_(Lambda) \
|
||||
_(LambdaArrow) \
|
||||
_(LambdaForSingleton) \
|
||||
_(LambdaPar) \
|
||||
_(ImplicitThis) \
|
||||
|
|
|
@ -2068,6 +2068,18 @@ LIRGenerator::visitLambda(MLambda *ins)
|
|||
return define(lir, ins) && assignSafepoint(lir, ins);
|
||||
}
|
||||
|
||||
bool
|
||||
LIRGenerator::visitLambdaArrow(MLambdaArrow *ins)
|
||||
{
|
||||
MOZ_ASSERT(ins->scopeChain()->type() == MIRType_Object);
|
||||
MOZ_ASSERT(ins->thisDef()->type() == MIRType_Value);
|
||||
|
||||
LLambdaArrow *lir = new(alloc()) LLambdaArrow(useRegister(ins->scopeChain()), temp());
|
||||
if (!useBox(lir, LLambdaArrow::ThisValue, ins->thisDef()))
|
||||
return false;
|
||||
return define(lir, ins) && assignSafepoint(lir, ins);
|
||||
}
|
||||
|
||||
bool
|
||||
LIRGenerator::visitLambdaPar(MLambdaPar *ins)
|
||||
{
|
||||
|
|
|
@ -154,6 +154,7 @@ class LIRGenerator : public LIRGeneratorSpecific
|
|||
bool visitRegExpReplace(MRegExpReplace *ins);
|
||||
bool visitStringReplace(MStringReplace *ins);
|
||||
bool visitLambda(MLambda *ins);
|
||||
bool visitLambdaArrow(MLambdaArrow *ins);
|
||||
bool visitLambdaPar(MLambdaPar *ins);
|
||||
bool visitImplicitThis(MImplicitThis *ins);
|
||||
bool visitSlots(MSlots *ins);
|
||||
|
|
|
@ -5085,6 +5085,44 @@ class MLambda
|
|||
}
|
||||
};
|
||||
|
||||
class MLambdaArrow
|
||||
: public MBinaryInstruction,
|
||||
public MixPolicy<ObjectPolicy<0>, BoxPolicy<1> >
|
||||
{
|
||||
LambdaFunctionInfo info_;
|
||||
|
||||
MLambdaArrow(types::CompilerConstraintList *constraints, MDefinition *scopeChain,
|
||||
MDefinition *this_, JSFunction *fun)
|
||||
: MBinaryInstruction(scopeChain, this_), info_(fun)
|
||||
{
|
||||
setResultType(MIRType_Object);
|
||||
MOZ_ASSERT(!types::UseNewTypeForClone(fun));
|
||||
if (!fun->hasSingletonType())
|
||||
setResultTypeSet(MakeSingletonTypeSet(constraints, fun));
|
||||
}
|
||||
|
||||
public:
|
||||
INSTRUCTION_HEADER(LambdaArrow)
|
||||
|
||||
static MLambdaArrow *New(TempAllocator &alloc, types::CompilerConstraintList *constraints,
|
||||
MDefinition *scopeChain, MDefinition *this_, JSFunction *fun)
|
||||
{
|
||||
return new(alloc) MLambdaArrow(constraints, scopeChain, this_, fun);
|
||||
}
|
||||
MDefinition *scopeChain() const {
|
||||
return getOperand(0);
|
||||
}
|
||||
MDefinition *thisDef() const {
|
||||
return getOperand(1);
|
||||
}
|
||||
const LambdaFunctionInfo &info() const {
|
||||
return info_;
|
||||
}
|
||||
TypePolicy *typePolicy() {
|
||||
return this;
|
||||
}
|
||||
};
|
||||
|
||||
class MLambdaPar
|
||||
: public MBinaryInstruction,
|
||||
public SingleObjectPolicy
|
||||
|
|
|
@ -107,6 +107,7 @@ namespace jit {
|
|||
_(RegExpReplace) \
|
||||
_(StringReplace) \
|
||||
_(Lambda) \
|
||||
_(LambdaArrow) \
|
||||
_(ImplicitThis) \
|
||||
_(Slots) \
|
||||
_(Elements) \
|
||||
|
|
|
@ -196,6 +196,7 @@ class ParallelSafetyVisitor : public MInstructionVisitor
|
|||
SAFE_OP(Nop)
|
||||
UNSAFE_OP(RegExp)
|
||||
CUSTOM_OP(Lambda)
|
||||
UNSAFE_OP(LambdaArrow)
|
||||
UNSAFE_OP(ImplicitThis)
|
||||
SAFE_OP(Slots)
|
||||
SAFE_OP(Elements)
|
||||
|
|
|
@ -1063,6 +1063,8 @@ CloneObject(JSContext *cx, HandleObject selfHostedObject)
|
|||
if (selfHostedObject->is<JSFunction>()) {
|
||||
RootedFunction selfHostedFunction(cx, &selfHostedObject->as<JSFunction>());
|
||||
bool hasName = selfHostedFunction->atom() != nullptr;
|
||||
// Arrow functions use the first extended slot for their lexical |this| value.
|
||||
JS_ASSERT(!selfHostedFunction->isArrow());
|
||||
js::gc::AllocKind kind = hasName
|
||||
? JSFunction::ExtendedFinalizeKind
|
||||
: selfHostedFunction->getAllocKind();
|
||||
|
|
Загрузка…
Ссылка в новой задаче