Backed out 3 changesets (bug 1378808) for failing spidermonkey builds on a CLOSED TREE

Backed out changeset 8658a25ee96b (bug 1378808)
Backed out changeset e761b8eef0aa (bug 1378808)
Backed out changeset b14186c3f895 (bug 1378808)
This commit is contained in:
Andreea Pavel 2018-07-27 23:06:00 +03:00
Родитель 806241e4f4
Коммит 1ea5273b59
16 изменённых файлов: 316 добавлений и 546 удалений

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

@ -2702,25 +2702,24 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst)
case ParseNodeKind::Call:
case ParseNodeKind::SuperCall:
{
ParseNode* pn_callee = pn->pn_left;
ParseNode* pn_args = pn->pn_right;
MOZ_ASSERT(pn->pn_pos.encloses(pn_callee->pn_pos));
ParseNode* next = pn->pn_head;
MOZ_ASSERT(pn->pn_pos.encloses(next->pn_pos));
RootedValue callee(cx);
if (pn->isKind(ParseNodeKind::SuperCall)) {
MOZ_ASSERT(pn_callee->isKind(ParseNodeKind::SuperBase));
if (!builder.super(&pn_callee->pn_pos, &callee))
MOZ_ASSERT(next->isKind(ParseNodeKind::SuperBase));
if (!builder.super(&next->pn_pos, &callee))
return false;
} else {
if (!expression(pn_callee, &callee))
if (!expression(next, &callee))
return false;
}
NodeVector args(cx);
if (!args.reserve(pn_args->pn_count))
if (!args.reserve(pn->pn_count - 1))
return false;
for (ParseNode* next = pn_args->pn_head; next; next = next->pn_next) {
for (next = next->pn_next; next; next = next->pn_next) {
MOZ_ASSERT(pn->pn_pos.encloses(next->pn_pos));
RootedValue arg(cx);
@ -2741,17 +2740,17 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst)
case ParseNodeKind::Dot:
{
MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_left->pn_pos));
MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_expr->pn_pos));
RootedValue expr(cx);
RootedValue propname(cx);
RootedAtom pnAtom(cx, pn->pn_right->pn_atom);
RootedAtom pnAtom(cx, pn->pn_atom);
if (pn->as<PropertyAccess>().isSuper()) {
if (!builder.super(&pn->pn_left->pn_pos, &expr))
if (!builder.super(&pn->pn_expr->pn_pos, &expr))
return false;
} else {
if (!expression(pn->pn_left, &expr))
if (!expression(pn->pn_expr, &expr))
return false;
}

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

@ -3462,8 +3462,9 @@ BinASTParser<Tok>::parseInterfaceCallExpression(const size_t start, const BinKin
op = parseContext_->sc()->strict() ? JSOP_STRICTEVAL : JSOP_EVAL;
}
}
BINJS_TRY_DECL(result, factory_.newCall(callee, arguments));
auto result = arguments;
result->setKind(ParseNodeKind::Call);
result->prepend(callee);
result->setOp(op);
return result;
}
@ -5676,7 +5677,10 @@ BinASTParser<Tok>::parseInterfaceNewExpression(const size_t start, const BinKind
BINJS_MOZ_TRY_DECL(arguments, parseArguments());
BINJS_TRY_DECL(result, factory_.newNewExpression(tokenizer_->pos(start).begin, callee, arguments));
auto result = arguments;
result->setKind(ParseNodeKind::New);
result->prepend(callee);
result->setOp(JSOP_NEW);
return result;
}
@ -6193,18 +6197,13 @@ BinASTParser<Tok>::parseInterfaceStaticMemberAssignmentTarget(const size_t start
const BinField expected_fields[2] = { BinField::Object, BinField::Property };
MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
#endif // defined(DEBUG)
TokenPos namePos;
BINJS_MOZ_TRY_DECL(object, parseExpressionOrSuper());
RootedAtom property(cx_);
{
namePos = tokenizer_->pos();
MOZ_TRY_VAR(property, tokenizer_->readAtom());
MOZ_TRY_VAR(property, tokenizer_->readAtom());
}
BINJS_TRY_DECL(name, factory_.newPropertyName(property->asPropertyName(), namePos));
BINJS_TRY_DECL(result, factory_.newPropertyAccess(object, name));
BINJS_TRY_DECL(result, factory_.newPropertyAccess(object, property->asPropertyName(), start));
return result;
}
@ -6243,18 +6242,13 @@ BinASTParser<Tok>::parseInterfaceStaticMemberExpression(const size_t start, cons
const BinField expected_fields[2] = { BinField::Object, BinField::Property };
MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
#endif // defined(DEBUG)
TokenPos namePos;
BINJS_MOZ_TRY_DECL(object, parseExpressionOrSuper());
RootedAtom property(cx_);
{
namePos = tokenizer_->pos();
MOZ_TRY_VAR(property, tokenizer_->readAtom());
MOZ_TRY_VAR(property, tokenizer_->readAtom());
}
BINJS_TRY_DECL(name, factory_.newPropertyName(property->asPropertyName(), namePos));
BINJS_TRY_DECL(result, factory_.newPropertyAccess(object, name));
BINJS_TRY_DECL(result, factory_.newPropertyAccess(object, property->asPropertyName(), start));
return result;
}

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

@ -428,8 +428,9 @@ CallExpression:
op = parseContext_->sc()->strict() ? JSOP_STRICTEVAL : JSOP_EVAL;
}
}
BINJS_TRY_DECL(result, factory_.newCall(callee, arguments));
auto result = arguments;
result->setKind(ParseNodeKind::Call);
result->prepend(callee);
result->setOp(op);
@ -830,7 +831,10 @@ LiteralStringExpression:
NewExpression:
build: |
BINJS_TRY_DECL(result, factory_.newNewExpression(tokenizer_->pos(start).begin, callee, arguments));
auto result = arguments;
result->setKind(ParseNodeKind::New);
result->prepend(callee);
result->setOp(JSOP_NEW);
ObjectExpression:
build:
@ -918,28 +922,12 @@ SwitchStatementWithDefault:
BINJS_TRY_DECL(result, factory_.newSwitchStatement(start, discriminant, scope));
StaticMemberAssignmentTarget:
init:
TokenPos namePos;
fields:
property:
block:
before: |
namePos = tokenizer_->pos();
build: |
BINJS_TRY_DECL(name, factory_.newPropertyName(property->asPropertyName(), namePos));
BINJS_TRY_DECL(result, factory_.newPropertyAccess(object, name));
BINJS_TRY_DECL(result, factory_.newPropertyAccess(object, property->asPropertyName(), start));
StaticMemberExpression:
init:
TokenPos namePos;
fields:
property:
block:
before: |
namePos = tokenizer_->pos();
build: |
BINJS_TRY_DECL(name, factory_.newPropertyName(property->asPropertyName(), namePos));
BINJS_TRY_DECL(result, factory_.newPropertyAccess(object, name));
BINJS_TRY_DECL(result, factory_.newPropertyAccess(object, property->asPropertyName(), start));
ThisExpression:
build: |

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

@ -1038,7 +1038,7 @@ BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer)
// Watch out for getters!
case ParseNodeKind::Dot:
MOZ_ASSERT(pn->isArity(PN_BINARY));
MOZ_ASSERT(pn->isArity(PN_NAME));
*answer = true;
return true;
@ -1276,14 +1276,6 @@ BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer)
case ParseNodeKind::Call:
case ParseNodeKind::TaggedTemplate:
case ParseNodeKind::SuperCall:
MOZ_ASSERT(pn->isArity(PN_BINARY));
*answer = true;
return true;
// Function arg lists can contain arbitrary expressions. Technically
// this only causes side-effects if one of the arguments does, but since
// the call being made will always trigger side-effects, it isn't needed.
case ParseNodeKind::Arguments:
MOZ_ASSERT(pn->isArity(PN_LIST));
*answer = true;
return true;
@ -1418,7 +1410,6 @@ BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer)
case ParseNodeKind::CallSiteObj: // by ParseNodeKind::TaggedTemplate
case ParseNodeKind::PosHolder: // by ParseNodeKind::NewTarget
case ParseNodeKind::SuperBase: // by ParseNodeKind::Elem and others
case ParseNodeKind::PropertyName: // by ParseNodeKind::Dot
MOZ_CRASH("handled by parent nodes");
case ParseNodeKind::Limit: // invalid sentinel value
@ -1890,11 +1881,11 @@ BytecodeEmitter::emitPropLHS(ParseNode* pn)
MOZ_ASSERT(pn->isKind(ParseNodeKind::Dot));
MOZ_ASSERT(!pn->as<PropertyAccess>().isSuper());
ParseNode* pn2 = pn->pn_left;
ParseNode* pn2 = pn->pn_expr;
/*
* If the object operand is also a dotted property reference, reverse the
* list linked via pn_left temporarily so we can iterate over it from the
* list linked via pn_expr temporarily so we can iterate over it from the
* bottom up (reversing again as we go), to avoid excessive recursion.
*/
if (pn2->isKind(ParseNodeKind::Dot) && !pn2->as<PropertyAccess>().isSuper()) {
@ -1902,9 +1893,9 @@ BytecodeEmitter::emitPropLHS(ParseNode* pn)
ParseNode* pnup = nullptr;
ParseNode* pndown;
for (;;) {
/* Reverse pndot->pn_left to point up, not down. */
pndown = pndot->pn_left;
pndot->pn_left = pnup;
/* Reverse pndot->pn_expr to point up, not down. */
pndown = pndot->pn_expr;
pndot->pn_expr = pnup;
if (!pndown->isKind(ParseNodeKind::Dot) || pndown->as<PropertyAccess>().isSuper())
break;
pnup = pndot;
@ -1917,12 +1908,12 @@ BytecodeEmitter::emitPropLHS(ParseNode* pn)
do {
/* Walk back up the list, emitting annotated name ops. */
if (!emitAtomOp(pndot->pn_right, JSOP_GETPROP))
if (!emitAtomOp(pndot, JSOP_GETPROP))
return false;
/* Reverse the pn_left link again. */
pnup = pndot->pn_left;
pndot->pn_left = pndown;
/* Reverse the pn_expr link again. */
pnup = pndot->pn_expr;
pndot->pn_expr = pndown;
pndown = pndot;
} while ((pndot = pnup) != nullptr);
return true;
@ -1947,7 +1938,7 @@ BytecodeEmitter::emitSuperPropLHS(ParseNode* superBase, bool isCall)
bool
BytecodeEmitter::emitPropOp(ParseNode* pn, JSOp op)
{
MOZ_ASSERT(pn->isArity(PN_BINARY));
MOZ_ASSERT(pn->isArity(PN_NAME));
if (!emitPropLHS(pn))
return false;
@ -1955,7 +1946,7 @@ BytecodeEmitter::emitPropOp(ParseNode* pn, JSOp op)
if (op == JSOP_CALLPROP && !emit1(JSOP_DUP))
return false;
if (!emitAtomOp(pn->pn_right, op))
if (!emitAtomOp(pn, op))
return false;
if (op == JSOP_CALLPROP && !emit1(JSOP_SWAP))
@ -1971,7 +1962,7 @@ BytecodeEmitter::emitSuperPropOp(ParseNode* pn, JSOp op, bool isCall)
if (!emitSuperPropLHS(base, isCall))
return false;
if (!emitAtomOp(pn->pn_right, op))
if (!emitAtomOp(pn, op))
return false;
if (isCall && !emit1(JSOP_SWAP))
@ -2001,7 +1992,7 @@ BytecodeEmitter::emitPropIncDec(ParseNode* pn)
if (!emit1(JSOP_DUP)) // OBJ OBJ
return false;
}
if (!emitAtomOp(pn->pn_kid->pn_right, isSuper ? JSOP_GETPROP_SUPER : JSOP_GETPROP)) // OBJ V
if (!emitAtomOp(pn->pn_kid, isSuper? JSOP_GETPROP_SUPER : JSOP_GETPROP)) // OBJ V
return false;
if (!emit1(JSOP_POS)) // OBJ N
return false;
@ -2027,7 +2018,7 @@ BytecodeEmitter::emitPropIncDec(ParseNode* pn)
JSOp setOp = isSuper ? sc->strict() ? JSOP_STRICTSETPROP_SUPER : JSOP_SETPROP_SUPER
: sc->strict() ? JSOP_STRICTSETPROP : JSOP_SETPROP;
if (!emitAtomOp(pn->pn_kid->pn_right, setOp)) // N? N+1
if (!emitAtomOp(pn->pn_kid, setOp)) // N? N+1
return false;
if (post && !emit1(JSOP_POP)) // RESULT
return false;
@ -2752,7 +2743,7 @@ BytecodeEmitter::emitDestructuringLHSRef(ParseNode* target, size_t* emitted)
return false;
*emitted = 2;
} else {
if (!emitTree(target->pn_left))
if (!emitTree(target->pn_expr))
return false;
*emitted = 1;
}
@ -2870,7 +2861,7 @@ BytecodeEmitter::emitSetOrInitializeDestructuring(ParseNode* target, Destructuri
setOp = sc->strict() ? JSOP_STRICTSETPROP_SUPER : JSOP_SETPROP_SUPER;
else
setOp = sc->strict() ? JSOP_STRICTSETPROP : JSOP_SETPROP;
if (!emitAtomOp(target->pn_right, setOp))
if (!emitAtomOp(target, setOp))
return false;
break;
}
@ -3982,11 +3973,11 @@ BytecodeEmitter::emitAssignment(ParseNode* lhs, ParseNodeKind pnk, ParseNode* rh
return false;
offset += 2;
} else {
if (!emitTree(lhs->pn_left))
if (!emitTree(lhs->expr()))
return false;
offset += 1;
}
if (!makeAtomIndex(lhs->pn_right->pn_atom, &atomIndex))
if (!makeAtomIndex(lhs->pn_atom, &atomIndex))
return false;
break;
case ParseNodeKind::Elem: {
@ -4035,7 +4026,7 @@ BytecodeEmitter::emitAssignment(ParseNode* lhs, ParseNodeKind pnk, ParseNode* rh
} else {
if (!emit1(JSOP_DUP))
return false;
bool isLength = (lhs->pn_right->pn_atom == cx->names().length);
bool isLength = (lhs->pn_atom == cx->names().length);
getOp = isLength ? JSOP_LENGTH : JSOP_GETPROP;
}
if (!emitIndex32(getOp, atomIndex))
@ -4882,7 +4873,7 @@ BytecodeEmitter::emitForOf(ParseNode* forOfLoop, EmitterScope* headLexicalEmitte
bool allowSelfHostedIter = false;
if (emitterMode == BytecodeEmitter::SelfHosting &&
forHeadExpr->isKind(ParseNodeKind::Call) &&
forHeadExpr->pn_left->name() == cx->names().allowContentIter)
forHeadExpr->pn_head->name() == cx->names().allowContentIter)
{
allowSelfHostedIter = true;
}
@ -6577,12 +6568,10 @@ BytecodeEmitter::emitSelfHostedCallFunction(ParseNode* pn)
//
// argc is set to the amount of actually emitted args and the
// emitting of args below is disabled by setting emitArgs to false.
ParseNode* pn_callee = pn->pn_left;
ParseNode* pn_args = pn->pn_right;
ParseNode* pn2 = pn->pn_head;
const char* errorName = SelfHostedCallFunctionName(pn2->name(), cx);
const char* errorName = SelfHostedCallFunctionName(pn_callee->name(), cx);
if (pn_args->pn_count < 2) {
if (pn->pn_count < 3) {
reportError(pn, JSMSG_MORE_ARGS_NEEDED, errorName, "2", "s");
return false;
}
@ -6593,8 +6582,8 @@ BytecodeEmitter::emitSelfHostedCallFunction(ParseNode* pn)
return false;
}
bool constructing = pn_callee->name() == cx->names().constructContentFunction;
ParseNode* funNode = pn_args->pn_head;
bool constructing = pn2->name() == cx->names().constructContentFunction;
ParseNode* funNode = pn2->pn_next;
if (constructing) {
callOp = JSOP_NEW;
} else if (funNode->getKind() == ParseNodeKind::Name &&
@ -6607,7 +6596,7 @@ BytecodeEmitter::emitSelfHostedCallFunction(ParseNode* pn)
#ifdef DEBUG
if (emitterMode == BytecodeEmitter::SelfHosting &&
pn_callee->name() == cx->names().callFunction)
pn2->name() == cx->names().callFunction)
{
if (!emit1(JSOP_DEBUGCHECKSELFHOSTED))
return false;
@ -6636,7 +6625,7 @@ BytecodeEmitter::emitSelfHostedCallFunction(ParseNode* pn)
return false;
}
uint32_t argc = pn_args->pn_count - 2;
uint32_t argc = pn->pn_count - 3;
if (!emitCall(callOp, argc))
return false;
@ -6647,15 +6636,15 @@ BytecodeEmitter::emitSelfHostedCallFunction(ParseNode* pn)
bool
BytecodeEmitter::emitSelfHostedResumeGenerator(ParseNode* pn)
{
ParseNode* pn_args = pn->pn_right;
// Syntax: resumeGenerator(gen, value, 'next'|'throw'|'return')
if (pn_args->pn_count != 3) {
if (pn->pn_count != 4) {
reportError(pn, JSMSG_MORE_ARGS_NEEDED, "resumeGenerator", "1", "s");
return false;
}
ParseNode* genNode = pn_args->pn_head;
ParseNode* funNode = pn->pn_head; // The resumeGenerator node.
ParseNode* genNode = funNode->pn_next;
if (!emitTree(genNode))
return false;
@ -6687,26 +6676,24 @@ BytecodeEmitter::emitSelfHostedForceInterpreter()
bool
BytecodeEmitter::emitSelfHostedAllowContentIter(ParseNode* pn)
{
ParseNode* pn_args = pn->pn_right;
if (pn_args->pn_count != 1) {
if (pn->pn_count != 2) {
reportError(pn, JSMSG_MORE_ARGS_NEEDED, "allowContentIter", "1", "");
return false;
}
// We're just here as a sentinel. Pass the value through directly.
return emitTree(pn_args->pn_head);
return emitTree(pn->pn_head->pn_next);
}
bool
BytecodeEmitter::emitSelfHostedDefineDataProperty(ParseNode* pn)
{
ParseNode* pn_args = pn->pn_right;
// Only optimize when 3 arguments are passed (we use 4 to include |this|).
MOZ_ASSERT(pn->pn_count == 4);
// Only optimize when 3 arguments are passed.
MOZ_ASSERT(pn_args->pn_count == 3);
ParseNode* funNode = pn->pn_head; // The _DefineDataProperty node.
ParseNode* objNode = pn_args->pn_head;
ParseNode* objNode = funNode->pn_next;
if (!emitTree(objNode))
return false;
@ -6727,14 +6714,14 @@ BytecodeEmitter::emitSelfHostedDefineDataProperty(ParseNode* pn)
bool
BytecodeEmitter::emitSelfHostedHasOwn(ParseNode* pn)
{
ParseNode* pn_args = pn->pn_right;
if (pn_args->pn_count != 2) {
if (pn->pn_count != 3) {
reportError(pn, JSMSG_MORE_ARGS_NEEDED, "hasOwn", "2", "");
return false;
}
ParseNode* idNode = pn_args->pn_head;
ParseNode* funNode = pn->pn_head; // The hasOwn node.
ParseNode* idNode = funNode->pn_next;
if (!emitTree(idNode))
return false;
@ -6748,14 +6735,14 @@ BytecodeEmitter::emitSelfHostedHasOwn(ParseNode* pn)
bool
BytecodeEmitter::emitSelfHostedGetPropertySuper(ParseNode* pn)
{
ParseNode* pn_args = pn->pn_right;
if (pn_args->pn_count != 3) {
if (pn->pn_count != 4) {
reportError(pn, JSMSG_MORE_ARGS_NEEDED, "getPropertySuper", "3", "");
return false;
}
ParseNode* objNode = pn_args->pn_head;
ParseNode* funNode = pn->pn_head; // The getPropertySuper node.
ParseNode* objNode = funNode->pn_next;
ParseNode* idNode = objNode->pn_next;
ParseNode* receiverNode = idNode->pn_next;
@ -6784,11 +6771,11 @@ BytecodeEmitter::isRestParameter(ParseNode* pn)
if (!pn->isKind(ParseNodeKind::Name)) {
if (emitterMode == BytecodeEmitter::SelfHosting && pn->isKind(ParseNodeKind::Call)) {
ParseNode* pn_callee = pn->pn_left;
if (pn_callee->getKind() == ParseNodeKind::Name &&
pn_callee->name() == cx->names().allowContentIter)
ParseNode* pn2 = pn->pn_head;
if (pn2->getKind() == ParseNodeKind::Name &&
pn2->name() == cx->names().allowContentIter)
{
return isRestParameter(pn->pn_right->pn_head);
return isRestParameter(pn2->pn_next);
}
}
return false;
@ -6918,22 +6905,101 @@ BytecodeEmitter::emitPipeline(ParseNode* pn)
}
bool
BytecodeEmitter::emitArguments(ParseNode* pn, bool callop, bool spread)
BytecodeEmitter::emitCallOrNew(ParseNode* pn, ValueUsage valueUsage /* = ValueUsage::WantValue */)
{
uint32_t argc = pn->pn_count;
bool callop =
pn->isKind(ParseNodeKind::Call) || pn->isKind(ParseNodeKind::TaggedTemplate);
/*
* Emit callable invocation or operator new (constructor call) code.
* First, emit code for the left operand to evaluate the callable or
* constructable object expression.
*
* For operator new, we emit JSOP_GETPROP instead of JSOP_CALLPROP, etc.
* This is necessary to interpose the lambda-initialized method read
* barrier -- see the code in jsinterp.cpp for JSOP_LAMBDA followed by
* JSOP_{SET,INIT}PROP.
*
* Then (or in a call case that has no explicit reference-base
* object) we emit JSOP_UNDEFINED to produce the undefined |this|
* value required for calls (which non-strict mode functions
* will box into the global object).
*/
uint32_t argc = pn->pn_count - 1;
if (argc >= ARGC_LIMIT) {
reportError(pn, callop ? JSMSG_TOO_MANY_FUN_ARGS : JSMSG_TOO_MANY_CON_ARGS);
return false;
}
ParseNode* pn2 = pn->pn_head;
bool spread = JOF_OPTYPE(pn->getOp()) == JOF_BYTE;
if (pn2->isKind(ParseNodeKind::Name) && emitterMode == BytecodeEmitter::SelfHosting && !spread) {
// Calls to "forceInterpreter", "callFunction",
// "callContentFunction", or "resumeGenerator" in self-hosted
// code generate inline bytecode.
if (pn2->name() == cx->names().callFunction ||
pn2->name() == cx->names().callContentFunction ||
pn2->name() == cx->names().constructContentFunction)
{
return emitSelfHostedCallFunction(pn);
}
if (pn2->name() == cx->names().resumeGenerator)
return emitSelfHostedResumeGenerator(pn);
if (pn2->name() == cx->names().forceInterpreter)
return emitSelfHostedForceInterpreter();
if (pn2->name() == cx->names().allowContentIter)
return emitSelfHostedAllowContentIter(pn);
if (pn2->name() == cx->names().defineDataPropertyIntrinsic && pn->pn_count == 4)
return emitSelfHostedDefineDataProperty(pn);
if (pn2->name() == cx->names().hasOwn)
return emitSelfHostedHasOwn(pn);
if (pn2->name() == cx->names().getPropertySuper)
return emitSelfHostedGetPropertySuper(pn);
// Fall through
}
if (!emitCallee(pn2, pn, &callop))
return false;
bool isNewOp = pn->getOp() == JSOP_NEW || pn->getOp() == JSOP_SPREADNEW ||
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
* JSOP_NEW bytecode with a two-byte immediate telling how many args
* were pushed on the operand stack.
*/
if (!spread) {
for (ParseNode* pn3 = pn->pn_head; pn3; pn3 = pn3->pn_next) {
for (ParseNode* pn3 = pn2->pn_next; pn3; pn3 = pn3->pn_next) {
if (!emitTree(pn3))
return false;
}
if (isNewOp) {
if (pn->isKind(ParseNodeKind::SuperCall)) {
if (!emit1(JSOP_NEWTARGET))
return false;
} else {
// Repush the callee as new.target
if (!emitDupAt(argc + 1))
return false;
}
}
} else {
ParseNode* args = pn->pn_head;
ParseNode* args = pn2->pn_next;
bool emitOptCode = (argc == 1) && isRestParameter(args->pn_kid);
InternalIfEmitter ifNotOptimizable(this);
@ -6973,159 +7039,29 @@ BytecodeEmitter::emitArguments(ParseNode* pn, bool callop, bool spread)
if (!ifNotOptimizable.emitEnd())
return false;
}
}
return true;
}
bool
BytecodeEmitter::emitCallOrNew(ParseNode* pn, ValueUsage valueUsage /* = ValueUsage::WantValue */)
{
bool callop =
pn->isKind(ParseNodeKind::Call) || pn->isKind(ParseNodeKind::TaggedTemplate);
/*
* Emit callable invocation or operator new (constructor call) code.
* First, emit code for the left operand to evaluate the callable or
* constructable object expression.
*
* For operator new, we emit JSOP_GETPROP instead of JSOP_CALLPROP, etc.
* This is necessary to interpose the lambda-initialized method read
* barrier -- see the code in jsinterp.cpp for JSOP_LAMBDA followed by
* JSOP_{SET,INIT}PROP.
*
* Then (or in a call case that has no explicit reference-base
* object) we emit JSOP_UNDEFINED to produce the undefined |this|
* value required for calls (which non-strict mode functions
* will box into the global object).
*/
ParseNode* pn_callee = pn->pn_left;
ParseNode* pn_args = pn->pn_right;
bool spread = JOF_OPTYPE(pn->getOp()) == JOF_BYTE;
if (pn_callee->isKind(ParseNodeKind::Name) && emitterMode == BytecodeEmitter::SelfHosting && !spread) {
// Calls to "forceInterpreter", "callFunction",
// "callContentFunction", or "resumeGenerator" in self-hosted
// code generate inline bytecode.
if (pn_callee->name() == cx->names().callFunction ||
pn_callee->name() == cx->names().callContentFunction ||
pn_callee->name() == cx->names().constructContentFunction)
{
return emitSelfHostedCallFunction(pn);
}
if (pn_callee->name() == cx->names().resumeGenerator)
return emitSelfHostedResumeGenerator(pn);
if (pn_callee->name() == cx->names().forceInterpreter)
return emitSelfHostedForceInterpreter();
if (pn_callee->name() == cx->names().allowContentIter)
return emitSelfHostedAllowContentIter(pn);
if (pn_callee->name() == cx->names().defineDataPropertyIntrinsic && pn_args->pn_count == 3)
return emitSelfHostedDefineDataProperty(pn);
if (pn_callee->name() == cx->names().hasOwn)
return emitSelfHostedHasOwn(pn);
if (pn_callee->name() == cx->names().getPropertySuper)
return emitSelfHostedGetPropertySuper(pn);
// Fall through
}
if (!emitCallee(pn_callee, pn, &callop))
return false;
bool isNewOp = pn->getOp() == JSOP_NEW || pn->getOp() == JSOP_SPREADNEW ||
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;
}
}
if (!emitArguments(pn_args, callop, spread))
return false;
uint32_t argc = pn_args->pn_count;
/*
* Emit code for each argument in order, then emit the JSOP_*CALL or
* JSOP_NEW bytecode with a two-byte immediate telling how many args
* were pushed on the operand stack.
*/
if (isNewOp) {
if (pn->isKind(ParseNodeKind::SuperCall)) {
if (!emit1(JSOP_NEWTARGET))
return false;
} else if (!spread) {
// Repush the callee as new.target
if (!emitDupAt(argc + 1))
return false;
} else {
if (!emitDupAt(2))
return false;
}
}
ParseNode* coordNode = pn;
if (pn->isOp(JSOP_CALL) || pn->isOp(JSOP_SPREADCALL)) {
switch (pn_callee->getKind()) {
case ParseNodeKind::Dot: {
// Check if this member is a simple chain of simple chain of
// property accesses, e.g. x.y.z, this.x.y, super.x.y
bool simpleDotChain = false;
for (ParseNode* cur = pn_callee; cur->isKind(ParseNodeKind::Dot); cur = cur->pn_left) {
ParseNode* left = cur->pn_left;
if (left->isKind(ParseNodeKind::Name) || left->isKind(ParseNodeKind::This) ||
left->isKind(ParseNodeKind::SuperBase))
{
simpleDotChain = true;
}
if (pn->isKind(ParseNodeKind::SuperCall)) {
if (!emit1(JSOP_NEWTARGET))
return false;
} else {
if (!emitDupAt(2))
return false;
}
if (!simpleDotChain) {
// obj().aprop() // expression
// ^ // column coord
//
// Note: Because of the constant folding logic in FoldElement,
// this case also applies for constant string properties.
//
// obj()['aprop']() // expression
// ^ // column coord
coordNode = pn_callee->pn_right;
}
break;
}
case ParseNodeKind::Elem:
// obj[expr]() // expression
// ^ // column coord
coordNode = pn_args;
break;
default:
break;
}
}
if (!spread) {
if (pn->getOp() == JSOP_CALL && valueUsage == ValueUsage::IgnoreValue) {
if (!emitCall(JSOP_CALL_IGNORES_RV, argc, coordNode))
if (!emitCall(JSOP_CALL_IGNORES_RV, argc, pn))
return false;
checkTypeSet(JSOP_CALL_IGNORES_RV);
} else {
if (!emitCall(pn->getOp(), argc, coordNode))
if (!emitCall(pn->getOp(), argc, pn))
return false;
checkTypeSet(pn->getOp());
}
} else {
if (coordNode) {
if (!updateSourceCoordNotes(coordNode->pn_pos.begin))
return false;
}
if (!emit1(pn->getOp()))
return false;
checkTypeSet(pn->getOp());
@ -7694,7 +7630,7 @@ BytecodeEmitter::emitArray(ParseNode* pn, uint32_t count)
if (emitterMode == BytecodeEmitter::SelfHosting &&
expr->isKind(ParseNodeKind::Call) &&
expr->pn_left->name() == cx->names().allowContentIter)
expr->pn_head->name() == cx->names().allowContentIter)
{
allowSelfHostedIter = true;
}
@ -8742,9 +8678,8 @@ BytecodeEmitter::emitTree(ParseNode* pn, ValueUsage valueUsage /* = ValueUsage::
return false;
break;
case ParseNodeKind::PropertyName:
case ParseNodeKind::PosHolder:
MOZ_FALLTHROUGH_ASSERT("Should never try to emit ParseNodeKind::PosHolder or ::Property");
MOZ_FALLTHROUGH_ASSERT("Should never try to emit ParseNodeKind::PosHolder");
default:
MOZ_ASSERT(0);

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

@ -806,7 +806,6 @@ struct MOZ_STACK_CLASS BytecodeEmitter
bool isRestParameter(ParseNode* pn);
MOZ_MUST_USE bool emitArguments(ParseNode* pn, bool callop, bool spread);
MOZ_MUST_USE bool emitCallOrNew(ParseNode* pn, ValueUsage valueUsage = ValueUsage::WantValue);
MOZ_MUST_USE bool emitSelfHostedCallFunction(ParseNode* pn);
MOZ_MUST_USE bool emitSelfHostedResumeGenerator(ParseNode* pn);

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

@ -347,10 +347,8 @@ ContainsHoistedDeclaration(JSContext* cx, ParseNode* node, bool* result)
case ParseNodeKind::Comma:
case ParseNodeKind::Array:
case ParseNodeKind::Object:
case ParseNodeKind::PropertyName:
case ParseNodeKind::Dot:
case ParseNodeKind::Elem:
case ParseNodeKind::Arguments:
case ParseNodeKind::Call:
case ParseNodeKind::Name:
case ParseNodeKind::TemplateString:
@ -1255,8 +1253,7 @@ FoldElement(JSContext* cx, ParseNode** nodePtr, PerHandlerParser<FullParseHandle
// Optimization 3: We have expr["foo"] where foo is not an index. Convert
// to a property access (like expr.foo) that optimizes better downstream.
ParseNode* nameNode = parser.newPropertyName(name, key->pn_pos);
ParseNode* dottedAccess = parser.newPropertyAccess(expr, nameNode);
ParseNode* dottedAccess = parser.newPropertyAccess(expr, name, node->pn_pos.end);
if (!dottedAccess)
return false;
dottedAccess->setInParens(node->isInParens());
@ -1412,9 +1409,8 @@ FoldCall(JSContext* cx, ParseNode* node, PerHandlerParser<FullParseHandler>& par
{
MOZ_ASSERT(node->isKind(ParseNodeKind::Call) ||
node->isKind(ParseNodeKind::SuperCall) ||
node->isKind(ParseNodeKind::New) ||
node->isKind(ParseNodeKind::TaggedTemplate));
MOZ_ASSERT(node->isArity(PN_BINARY));
MOZ_ASSERT(node->isArity(PN_LIST));
// Don't fold a parenthesized callable component in an invocation, as this
// might cause a different |this| value to be used, changing semantics:
@ -1427,26 +1423,10 @@ FoldCall(JSContext* cx, ParseNode* node, PerHandlerParser<FullParseHandler>& par
// assertEq(obj.f``, "obj");
//
// See bug 537673 and bug 1182373.
ParseNode** pn_callee = &node->pn_left;
if (node->isKind(ParseNodeKind::New) || !(*pn_callee)->isInParens()) {
if (!Fold(cx, pn_callee, parser))
return false;
}
ParseNode** pn_args = &node->pn_right;
if (!Fold(cx, pn_args, parser))
return false;
return true;
}
static bool
FoldArguments(JSContext* cx, ParseNode* node, PerHandlerParser<FullParseHandler>& parser)
{
MOZ_ASSERT(node->isKind(ParseNodeKind::Arguments));
MOZ_ASSERT(node->isArity(PN_LIST));
ParseNode** listp = &node->pn_head;
if ((*listp)->isInParens())
listp = &(*listp)->pn_next;
for (; *listp; listp = &(*listp)->pn_next) {
if (!Fold(cx, listp, parser))
return false;
@ -1502,14 +1482,14 @@ static bool
FoldDottedProperty(JSContext* cx, ParseNode* node, PerHandlerParser<FullParseHandler>& parser)
{
MOZ_ASSERT(node->isKind(ParseNodeKind::Dot));
MOZ_ASSERT(node->isArity(PN_BINARY));
MOZ_ASSERT(node->isArity(PN_NAME));
// Iterate through a long chain of dotted property accesses to find the
// most-nested non-dotted property node, then fold that.
ParseNode** nested = &node->pn_left;
ParseNode** nested = &node->pn_expr;
while ((*nested)->isKind(ParseNodeKind::Dot)) {
MOZ_ASSERT((*nested)->isArity(PN_BINARY));
nested = &(*nested)->pn_left;
MOZ_ASSERT((*nested)->isArity(PN_NAME));
nested = &(*nested)->pn_expr;
}
return Fold(cx, nested, parser);
@ -1662,6 +1642,7 @@ Fold(JSContext* cx, ParseNode** pnp, PerHandlerParser<FullParseHandler>& parser)
case ParseNodeKind::InstanceOf:
case ParseNodeKind::In:
case ParseNodeKind::Comma:
case ParseNodeKind::New:
case ParseNodeKind::Array:
case ParseNodeKind::Object:
case ParseNodeKind::StatementList:
@ -1713,14 +1694,10 @@ Fold(JSContext* cx, ParseNode** pnp, PerHandlerParser<FullParseHandler>& parser)
return FoldAdd(cx, pnp, parser);
case ParseNodeKind::Call:
case ParseNodeKind::New:
case ParseNodeKind::SuperCall:
case ParseNodeKind::TaggedTemplate:
return FoldCall(cx, pn, parser);
case ParseNodeKind::Arguments:
return FoldArguments(cx, pn, parser);
case ParseNodeKind::Switch:
case ParseNodeKind::Colon:
case ParseNodeKind::Assign:
@ -1800,9 +1777,6 @@ Fold(JSContext* cx, ParseNode** pnp, PerHandlerParser<FullParseHandler>& parser)
MOZ_ASSERT(pn->isArity(PN_NAME));
return Fold(cx, &pn->pn_expr, parser);
case ParseNodeKind::PropertyName:
MOZ_CRASH("unreachable, handled by ::Dot");
case ParseNodeKind::Dot:
return FoldDottedProperty(cx, pn, parser);

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

@ -275,20 +275,16 @@ class FullParseHandler
addList(/* list = */ literal, /* child = */ element);
}
ParseNode* newCall(ParseNode* callee, ParseNode* args) {
return new_<BinaryNode>(ParseNodeKind::Call, JSOP_CALL, callee, args);
ParseNode* newCall(const TokenPos& pos) {
return new_<ListNode>(ParseNodeKind::Call, JSOP_CALL, pos);
}
ParseNode* newArguments(const TokenPos& pos) {
return new_<ListNode>(ParseNodeKind::Arguments, JSOP_NOP, pos);
ParseNode* newSuperCall(ParseNode* callee) {
return new_<ListNode>(ParseNodeKind::SuperCall, JSOP_SUPERCALL, callee);
}
ParseNode* newSuperCall(ParseNode* callee, ParseNode* args) {
return new_<BinaryNode>(ParseNodeKind::SuperCall, JSOP_SUPERCALL, callee, args);
}
ParseNode* newTaggedTemplate(ParseNode* tag, ParseNode* args) {
return new_<BinaryNode>(ParseNodeKind::TaggedTemplate, JSOP_CALL, tag, args);
ParseNode* newTaggedTemplate(const TokenPos& pos) {
return new_<ListNode>(ParseNodeKind::TaggedTemplate, JSOP_CALL, pos);
}
ParseNode* newObjectLiteral(uint32_t begin) {
@ -663,12 +659,8 @@ class FullParseHandler
return new_<DebuggerStatement>(pos);
}
ParseNode* newPropertyName(PropertyName* name, const TokenPos& pos) {
return new_<NameNode>(ParseNodeKind::PropertyName, JSOP_NOP, name, pos);
}
ParseNode* newPropertyAccess(ParseNode* expr, ParseNode* key) {
return new_<PropertyAccess>(expr, key, expr->pn_pos.begin, key->pn_pos.end);
ParseNode* newPropertyAccess(ParseNode* expr, PropertyName* key, uint32_t end) {
return new_<PropertyAccess>(expr, key, expr->pn_pos.begin, end);
}
ParseNode* newPropertyByValue(ParseNode* lhs, ParseNode* index, uint32_t end) {
@ -742,8 +734,13 @@ class FullParseHandler
return new_<LexicalScopeNode>(bindings, body);
}
Node newNewExpression(uint32_t begin, ParseNode* ctor, ParseNode* args) {
return new_<BinaryNode>(ParseNodeKind::New, JSOP_NEW, TokenPos(begin, args->pn_pos.end), ctor, args);
Node newNewExpression(uint32_t begin, ParseNode* ctor) {
ParseNode* newExpr = new_<ListNode>(ParseNodeKind::New, JSOP_NEW, TokenPos(begin, begin + 1));
if (!newExpr)
return nullptr;
addList(/* list = */ newExpr, /* child = */ ctor);
return newExpr;
}
ParseNode* newAssignment(ParseNodeKind kind, ParseNode* lhs, ParseNode* rhs) {

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

@ -75,11 +75,11 @@ class NameResolver
bool nameExpression(ParseNode* n, bool* foundName) {
switch (n->getKind()) {
case ParseNodeKind::Dot:
if (!nameExpression(n->pn_left, foundName))
if (!nameExpression(n->expr(), foundName))
return false;
if (!*foundName)
return true;
return appendPropertyReference(n->pn_right->pn_atom);
return appendPropertyReference(n->pn_atom);
case ParseNodeKind::Name:
*foundName = true;
@ -315,17 +315,17 @@ class NameResolver
bool resolveTaggedTemplate(ParseNode* node, HandleAtom prefix) {
MOZ_ASSERT(node->isKind(ParseNodeKind::TaggedTemplate));
ParseNode* tag = node->pn_left;
ParseNode* element = node->pn_head;
// The leading expression, e.g. |tag| in |tag`foo`|,
// The list head is a leading expression, e.g. |tag| in |tag`foo`|,
// that might contain functions.
if (!resolve(tag, prefix))
if (!resolve(element, prefix))
return false;
// The callsite object node is first. This node only contains
// Next is the callsite object node. This node only contains
// internal strings or undefined and an array -- no user-controlled
// expressions.
ParseNode* element = node->pn_right->pn_head;
element = element->pn_next;
#ifdef DEBUG
{
MOZ_ASSERT(element->isKind(ParseNodeKind::CallSiteObj));
@ -697,6 +697,9 @@ class NameResolver
case ParseNodeKind::Pow:
case ParseNodeKind::Pipeline:
case ParseNodeKind::Comma:
case ParseNodeKind::New:
case ParseNodeKind::Call:
case ParseNodeKind::SuperCall:
case ParseNodeKind::Array:
case ParseNodeKind::StatementList:
case ParseNodeKind::ParamsBody:
@ -730,32 +733,11 @@ class NameResolver
break;
case ParseNodeKind::TaggedTemplate:
MOZ_ASSERT(cur->isArity(PN_BINARY));
MOZ_ASSERT(cur->isArity(PN_LIST));
if (!resolveTaggedTemplate(cur, prefix))
return false;
break;
case ParseNodeKind::New:
case ParseNodeKind::Call:
case ParseNodeKind::SuperCall:
MOZ_ASSERT(cur->isArity(PN_BINARY));
if (!resolve(cur->pn_left, prefix))
return false;
if (!resolve(cur->pn_right, prefix))
return false;
break;
// Handles the arguments for new/call/supercall, but does _not_ handle
// the Arguments node used by tagged template literals, since that is
// special-cased inside of resolveTaggedTemplate.
case ParseNodeKind::Arguments:
MOZ_ASSERT(cur->isArity(PN_LIST));
for (ParseNode* element = cur->pn_head; element; element = element->pn_next) {
if (!resolve(element, prefix))
return false;
}
break;
// Import/export spec lists contain import/export specs containing
// only pairs of names. Alternatively, an export spec lists may
// contain a single export batch specifier.
@ -784,12 +766,12 @@ class NameResolver
}
case ParseNodeKind::Dot:
MOZ_ASSERT(cur->isArity(PN_BINARY));
MOZ_ASSERT(cur->isArity(PN_NAME));
// Super prop nodes do not have a meaningful LHS
if (cur->as<PropertyAccess>().isSuper())
break;
if (!resolve(cur->pn_left, prefix))
if (!resolve(cur->expr(), prefix))
return false;
break;
@ -828,7 +810,6 @@ class NameResolver
case ParseNodeKind::ExportSpec: // by ParseNodeKind::ExportSpecList
case ParseNodeKind::CallSiteObj: // by ParseNodeKind::TaggedTemplate
case ParseNodeKind::ClassNames: // by ParseNodeKind::Class
case ParseNodeKind::PropertyName: // by ParseNodeKind::Dot
MOZ_CRASH("should have been handled by a parent node");
case ParseNodeKind::Limit: // invalid sentinel value

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

@ -216,21 +216,6 @@ UnaryNode::dump(GenericPrinter& out, int indent)
void
BinaryNode::dump(GenericPrinter& out, int indent)
{
if (isKind(ParseNodeKind::Dot)) {
out.put("(.");
DumpParseTree(pn_right, out, indent + 2);
out.putChar(' ');
if (as<PropertyAccess>().isSuper())
out.put("super");
else
DumpParseTree(pn_left, out, indent + 2);
out.printf(")");
return;
}
const char* name = parseNodeNames[size_t(getKind())];
out.printf("(%s ", name);
indent += strlen(name) + 2;
@ -303,7 +288,10 @@ DumpName(GenericPrinter& out, const CharT* s, size_t len)
void
NameNode::dump(GenericPrinter& out, int indent)
{
if (isKind(ParseNodeKind::Name) || isKind(ParseNodeKind::PropertyName)) {
if (isKind(ParseNodeKind::Name) || isKind(ParseNodeKind::Dot)) {
if (isKind(ParseNodeKind::Dot))
out.put("(.");
if (!pn_atom) {
out.put("#<null name>");
} else if (getOp() == JSOP_GETARG && pn_atom->length() == 0) {
@ -318,6 +306,15 @@ NameNode::dump(GenericPrinter& out, int indent)
else
DumpName(out, pn_atom->twoByteChars(nogc), pn_atom->length());
}
if (isKind(ParseNodeKind::Dot)) {
out.putChar(' ');
if (as<PropertyAccess>().isSuper())
out.put("super");
else
DumpParseTree(expr(), out, indent + 2);
out.printf(")");
}
return;
}

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

@ -55,7 +55,6 @@ class ObjectBox;
F(PostIncrement) \
F(PreDecrement) \
F(PostDecrement) \
F(PropertyName) \
F(Dot) \
F(Elem) \
F(Array) \
@ -64,7 +63,6 @@ class ObjectBox;
F(Label) \
F(Object) \
F(Call) \
F(Arguments) \
F(Name) \
F(ObjectPropertyName) \
F(ComputedName) \
@ -372,8 +370,9 @@ IsTypeofKind(ParseNodeKind kind)
* PostIncrement,
* PreDecrement,
* PostDecrement
* New binary pn_left: ctor expression on the left of the (
* pn_right: Arguments
* New list pn_head: list of ctor, arg1, arg2, ... argN
* pn_count: 1 + N (where N is number of args)
* ctor is a MEMBER expr
* DeleteName unary pn_kid: Name expr
* DeleteProp unary pn_kid: Dot expr
* DeleteElem unary pn_kid: Elem expr
@ -382,15 +381,13 @@ IsTypeofKind(ParseNodeKind kind)
* for a more-specific PNK_DELETE* unless constant
* folding (or a similar parse tree manipulation) has
* occurred
* PropertyName name pn_atom: property name being accessed
* Dot binary pn_left: MEMBER expr to left of .
* pn_right: PropertyName to right of .
* Dot name pn_expr: MEMBER expr to left of .
* pn_atom: name to right of .
* Elem binary pn_left: MEMBER expr to left of [
* pn_right: expr between [ and ]
* Call binary pn_left: callee expression on the left of the (
* pn_right: Arguments
* Arguments list pn_head: list of arg1, arg2, ... argN
* pn_count: N (where N is number of args)
* Call list pn_head: list of call, arg1, arg2, ... argN
* pn_count: 1 + N (where N is number of args)
* call is a MEMBER expr naming a callable object
* Array list pn_head: list of pn_count array element exprs
* [,,] holes are represented by Elision nodes
* pn_xflags: PN_ENDCOMMA if extra comma at end
@ -410,9 +407,8 @@ IsTypeofKind(ParseNodeKind kind)
* list
* TemplateString pn_atom: template string atom
nullary pn_op: JSOP_NOP
* TaggedTemplate pn_left: tag expression
* binary pn_right: Arguments, with the first being the
* call site object, then arg1, arg2, ... argN
* TaggedTemplate pn_head: list of call, call site object, arg1, arg2, ... argN
* list pn_count: 2 + N (N is the number of substitutions)
* CallSiteObj list pn_head: a Array node followed by
* list of pn_count - 1 TemplateString nodes
* RegExp nullary pn_objbox: RegExp model object
@ -424,7 +420,7 @@ IsTypeofKind(ParseNodeKind kind)
*
* This, unary pn_kid: '.this' Name if function `this`, else nullptr
* SuperBase unary pn_kid: '.this' Name
* SuperCall binary pn_left: SuperBase pn_right: Arguments
*
* SetThis binary pn_left: '.this' Name, pn_right: SuperCall
*
* LexicalScope scope pn_u.scope.bindings: scope bindings
@ -573,7 +569,8 @@ class ParseNode
FunctionBox* funbox; /* function object */
};
ParseNode* expr; /* module or function body, var
initializer, or argument default */
initializer, argument default, or
base object of ParseNodeKind::Dot */
} name;
struct {
LexicalScope::Data* bindings;
@ -1177,33 +1174,30 @@ class RegExpLiteral : public NullaryNode
}
};
class PropertyAccess : public BinaryNode
class PropertyAccess : public ParseNode
{
public:
/*
* PropertyAccess nodes can have any expression/'super' as left-hand
* side, but the name must be a ParseNodeKind::PropertyName node.
*/
PropertyAccess(ParseNode* lhs, ParseNode* name, uint32_t begin, uint32_t end)
: BinaryNode(ParseNodeKind::Dot, JSOP_NOP, TokenPos(begin, end), lhs, name)
PropertyAccess(ParseNode* lhs, PropertyName* name, uint32_t begin, uint32_t end)
: ParseNode(ParseNodeKind::Dot, JSOP_NOP, PN_NAME, TokenPos(begin, end))
{
MOZ_ASSERT(lhs != nullptr);
MOZ_ASSERT(name != nullptr);
pn_u.name.expr = lhs;
pn_u.name.atom = name;
}
static bool test(const ParseNode& node) {
bool match = node.isKind(ParseNodeKind::Dot);
MOZ_ASSERT_IF(match, node.isArity(PN_BINARY));
MOZ_ASSERT_IF(match, node.pn_right->isKind(ParseNodeKind::PropertyName));
MOZ_ASSERT_IF(match, node.isArity(PN_NAME));
return match;
}
ParseNode& expression() const {
return *pn_u.binary.left;
return *pn_u.name.expr;
}
PropertyName& name() const {
return *pn_u.binary.right->pn_atom->asPropertyName();
return *pn_u.name.atom->asPropertyName();
}
bool isSuper() const {

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

@ -3395,13 +3395,13 @@ GeneralParser<ParseHandler, CharT>::addExprAndGetNextTemplStrToken(YieldHandling
template <class ParseHandler, typename CharT>
bool
GeneralParser<ParseHandler, CharT>::taggedTemplate(YieldHandling yieldHandling, Node tagArgsList,
GeneralParser<ParseHandler, CharT>::taggedTemplate(YieldHandling yieldHandling, Node nodeList,
TokenKind tt)
{
Node callSiteObjNode = handler.newCallSiteObject(pos().begin);
if (!callSiteObjNode)
return false;
handler.addList(tagArgsList, callSiteObjNode);
handler.addList(nodeList, callSiteObjNode);
while (true) {
if (!appendToCallSiteObj(callSiteObjNode))
@ -3409,10 +3409,10 @@ GeneralParser<ParseHandler, CharT>::taggedTemplate(YieldHandling yieldHandling,
if (tt != TokenKind::TemplateHead)
break;
if (!addExprAndGetNextTemplStrToken(yieldHandling, tagArgsList, &tt))
if (!addExprAndGetNextTemplStrToken(yieldHandling, nodeList, &tt))
return false;
}
handler.setEndPosition(tagArgsList, callSiteObjNode);
handler.setEndPosition(nodeList, callSiteObjNode);
return true;
}
@ -8631,25 +8631,24 @@ GeneralParser<ParseHandler, CharT>::assignExprWithoutYieldOrAwait(YieldHandling
}
template <class ParseHandler, typename CharT>
typename ParseHandler::Node
GeneralParser<ParseHandler, CharT>::argumentList(YieldHandling yieldHandling, bool* isSpread,
bool
GeneralParser<ParseHandler, CharT>::argumentList(YieldHandling yieldHandling, Node listNode,
bool* isSpread,
PossibleError* possibleError /* = nullptr */)
{
Node argsList = handler.newArguments(pos());
bool matched;
if (!tokenStream.matchToken(&matched, TokenKind::Rp, TokenStream::Operand))
return null();
return false;
if (matched) {
handler.setEndPosition(argsList, pos().end);
return argsList;
handler.setEndPosition(listNode, pos().end);
return true;
}
while (true) {
bool spread = false;
uint32_t begin = 0;
if (!tokenStream.matchToken(&matched, TokenKind::TripleDot, TokenStream::Operand))
return null();
return false;
if (matched) {
spread = true;
begin = pos().begin;
@ -8658,18 +8657,18 @@ GeneralParser<ParseHandler, CharT>::argumentList(YieldHandling yieldHandling, bo
Node argNode = assignExpr(InAllowed, yieldHandling, TripledotProhibited, possibleError);
if (!argNode)
return null();
return false;
if (spread) {
argNode = handler.newSpread(begin, argNode);
if (!argNode)
return null();
return false;
}
handler.addList(argsList, argNode);
handler.addList(listNode, argNode);
bool matched;
if (!tokenStream.matchToken(&matched, TokenKind::Comma, TokenStream::Operand))
return null();
return false;
if (!matched)
break;
@ -8682,8 +8681,8 @@ GeneralParser<ParseHandler, CharT>::argumentList(YieldHandling yieldHandling, bo
MUST_MATCH_TOKEN_MOD(TokenKind::Rp, TokenStream::Operand, JSMSG_PAREN_AFTER_ARGS);
handler.setEndPosition(argsList, pos().end);
return argsList;
handler.setEndPosition(listNode, pos().end);
return true;
}
bool
@ -8729,27 +8728,20 @@ GeneralParser<ParseHandler, CharT>::memberExpr(YieldHandling yieldHandling,
if (!ctorExpr)
return null();
bool matched;
if (!tokenStream.matchToken(&matched, TokenKind::Lp))
return null();
bool isSpread = false;
Node args;
if (matched) {
args = argumentList(yieldHandling, &isSpread);
} else {
args = handler.newArguments(pos());
}
if (!args)
return null();
lhs = handler.newNewExpression(newBegin, ctorExpr, args);
lhs = handler.newNewExpression(newBegin, ctorExpr);
if (!lhs)
return null();
if (isSpread)
handler.setOp(lhs, JSOP_SPREADNEW);
bool matched;
if (!tokenStream.matchToken(&matched, TokenKind::Lp))
return null();
if (matched) {
bool isSpread = false;
if (!argumentList(yieldHandling, lhs, &isSpread))
return null();
if (isSpread)
handler.setOp(lhs, JSOP_SPREADNEW);
}
}
} else if (tt == TokenKind::Super) {
Node thisName = newThisName();
@ -8786,12 +8778,7 @@ GeneralParser<ParseHandler, CharT>::memberExpr(YieldHandling yieldHandling,
error(JSMSG_BAD_SUPERPROP, "property");
return null();
}
Node name = handler.newPropertyName(field, pos());
if (!name)
return null();
nextMember = handler.newPropertyAccess(lhs, name);
nextMember = handler.newPropertyAccess(lhs, field, pos().end);
if (!nextMember)
return null();
} else {
@ -8827,16 +8814,15 @@ GeneralParser<ParseHandler, CharT>::memberExpr(YieldHandling yieldHandling,
return null();
}
nextMember = handler.newSuperCall(lhs);
if (!nextMember)
return null();
// Despite the fact that it's impossible to have |super()| in a
// generator, we still inherit the yieldHandling of the
// memberExpression, per spec. Curious.
bool isSpread = false;
Node args = argumentList(yieldHandling, &isSpread);
if (!args)
return null();
nextMember = handler.newSuperCall(lhs, args);
if (!nextMember)
if (!argumentList(yieldHandling, nextMember, &isSpread))
return null();
if (isSpread)
@ -8855,6 +8841,13 @@ GeneralParser<ParseHandler, CharT>::memberExpr(YieldHandling yieldHandling,
return null();
}
TokenPos nextMemberPos = pos();
nextMember = tt == TokenKind::Lp
? handler.newCall(nextMemberPos)
: handler.newTaggedTemplate(nextMemberPos);
if (!nextMember)
return null();
JSOp op = JSOP_CALL;
bool maybeAsyncArrow = false;
if (PropertyName* prop = handler.maybeDottedProperty(lhs)) {
@ -8896,11 +8889,13 @@ GeneralParser<ParseHandler, CharT>::memberExpr(YieldHandling yieldHandling,
}
}
handler.setBeginPosition(nextMember, lhs);
handler.addList(nextMember, lhs);
if (tt == TokenKind::Lp) {
bool isSpread = false;
PossibleError* asyncPossibleError = maybeAsyncArrow ? possibleError : nullptr;
Node args = argumentList(yieldHandling, &isSpread, asyncPossibleError);
if (!args)
if (!argumentList(yieldHandling, nextMember, &isSpread, asyncPossibleError))
return null();
if (isSpread) {
if (op == JSOP_EVAL)
@ -8910,20 +8905,8 @@ GeneralParser<ParseHandler, CharT>::memberExpr(YieldHandling yieldHandling,
else
op = JSOP_SPREADCALL;
}
nextMember = handler.newCall(lhs, args);
if (!nextMember)
return null();
} else {
Node args = handler.newArguments(pos());
if (!args)
return null();
if (!taggedTemplate(yieldHandling, args, tt))
return null();
nextMember = handler.newTaggedTemplate(lhs, args);
if (!nextMember)
if (!taggedTemplate(yieldHandling, nextMember, tt))
return null();
}
handler.setOp(nextMember, op);

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

@ -569,12 +569,8 @@ class MOZ_STACK_CLASS PerHandlerParser
bool isValidSimpleAssignmentTarget(Node node,
FunctionCallBehavior behavior = ForbidAssignmentToFunctionCalls);
Node newPropertyName(PropertyName* key, const TokenPos& pos) {
return handler.newPropertyName(key, pos);
}
Node newPropertyAccess(Node expr, Node key) {
return handler.newPropertyAccess(expr, key);
Node newPropertyAccess(Node expr, PropertyName* key, uint32_t end) {
return handler.newPropertyAccess(expr, key, end);
}
FunctionBox* newFunctionBox(Node fn, JSFunction* fun, uint32_t toStringStart,
@ -1159,7 +1155,7 @@ class MOZ_STACK_CLASS GeneralParser
Node condition(InHandling inHandling, YieldHandling yieldHandling);
Node argumentList(YieldHandling yieldHandling, bool* isSpread,
bool argumentList(YieldHandling yieldHandling, Node listNode, bool* isSpread,
PossibleError* possibleError = nullptr);
Node destructuringDeclaration(DeclarationKind kind, YieldHandling yieldHandling,
TokenKind tt);

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

@ -248,11 +248,9 @@ class SyntaxParseHandler
MOZ_MUST_USE bool addSpreadElement(Node literal, uint32_t begin, Node inner) { return true; }
void addArrayElement(Node literal, Node element) { }
Node newArguments(const TokenPos& pos) { return NodeGeneric; }
Node newCall(Node callee, Node args) { return NodeFunctionCall; }
Node newSuperCall(Node callee, Node args) { return NodeGeneric; }
Node newTaggedTemplate(Node callee, Node args) { return NodeGeneric; }
Node newCall(const TokenPos& pos) { return NodeFunctionCall; }
Node newSuperCall(Node callee) { return NodeGeneric; }
Node newTaggedTemplate(const TokenPos& pos) { return NodeGeneric; }
Node newObjectLiteral(uint32_t begin) { return NodeUnparenthesizedObject; }
Node newClassMethodList(uint32_t begin) { return NodeGeneric; }
@ -330,12 +328,8 @@ class SyntaxParseHandler
}
Node newDebuggerStatement(const TokenPos& pos) { return NodeGeneric; }
Node newPropertyName(PropertyName* name, const TokenPos& pos) {
lastAtom = name;
return NodeGeneric;
}
Node newPropertyAccess(Node expr, Node key) {
Node newPropertyAccess(Node expr, PropertyName* key, uint32_t end) {
lastAtom = key;
return NodeDottedProperty;
}
@ -430,7 +424,7 @@ class SyntaxParseHandler
list == NodeFunctionCall);
}
Node newNewExpression(uint32_t begin, Node ctor, Node args) {
Node newNewExpression(uint32_t begin, Node ctor) {
return NodeGeneric;
}

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

@ -33,12 +33,7 @@ function assertOffsetColumns(code, expectedBpts, expectedOrdering = null) {
// Set breakpoints everywhere and call the function.
const dbg = new Debugger;
let debuggeeFn = dbg.addDebuggee(global).makeDebuggeeValue(global.f);
if (debuggeeFn.isBoundFunction) {
debuggeeFn = debuggeeFn.boundTargetFunction;
}
const { script } = debuggeeFn;
const script = dbg.addDebuggee(global).makeDebuggeeValue(global.f).script;
for (const offset of script.getAllColumnOffsets()) {
assertEq(offset.lineNumber, 1);
assertEq(offset.columnNumber < execCode.length, true);

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

@ -83,58 +83,3 @@ assertOffsetColumns(
"function f(n) { do { print(n); } while(false); }",
" ^ ^ ^",
);
// getColumnOffsets correctly places the part of normal ::Dot node with identifier root.
assertOffsetColumns(
"var args = [];\n" +
"var obj = { base: { a(){ return { b(){} }; } } };\n" +
"function f(n) { obj.base.a().b(...args); }",
" ^ ^ ^ ^",
"0 2 1 3",
);
// getColumnOffsets correctly places the part of normal ::Dot node with "this" root.
assertOffsetColumns(
"var args = [];\n" +
"var obj = { base: { a(){ return { b(){} }; } } };\n" +
"var f = function() { this.base.a().b(...args); }.bind(obj);",
" ^ ^ ^ ^",
"0 2 1 3",
);
// getColumnOffsets correctly places the part of normal ::Dot node with "super" base.
assertOffsetColumns(
"var args = [];\n" +
"var obj = { base: { a(){ return { b(){} }; } } };\n" +
"var f = { __proto__: obj, f(n) { super.base.a().b(...args); } }.f;",
" ^ ^ ^ ^",
"0 2 1 3",
);
// getColumnOffsets correctly places the part of normal ::Dot node with other base.
assertOffsetColumns(
"var args = [];\n" +
"var obj = { base: { a(){ return { b(){} }; } } };\n" +
"function f(n) { (0, obj).base.a().b(...args); }",
" ^ ^ ^ ^ ^ ^",
"0 1 2 4 3 5",
);
// getColumnOffsets correctly places the part of folded ::Elem node.
assertOffsetColumns(
"var args = [];\n" +
"var obj = { base: { a(){ return { b(){} }; } } };\n" +
// Constant folding makes the static string behave like a dot access.
"function f(n) { obj.base['a']()['b'](...args); }",
" ^ ^ ^ ^",
"0 2 1 3",
);
// getColumnOffsets correctly places the part of computed ::Elem node.
assertOffsetColumns(
"var args = [], a = 'a', b = 'b';\n" +
"var obj = { base: { a(){ return { b(){} }; } } };\n" +
"function f(n) { obj.base[a]()[b](...args); }",
" ^ ^ ^^ ^",
"0 1 3 2 4",
);

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

@ -438,21 +438,22 @@ static inline ParseNode*
CallCallee(ParseNode* pn)
{
MOZ_ASSERT(pn->isKind(ParseNodeKind::Call));
return BinaryLeft(pn);
return ListHead(pn);
}
static inline unsigned
CallArgListLength(ParseNode* pn)
{
MOZ_ASSERT(pn->isKind(ParseNodeKind::Call));
return ListLength(BinaryRight(pn));
MOZ_ASSERT(ListLength(pn) >= 1);
return ListLength(pn) - 1;
}
static inline ParseNode*
CallArgList(ParseNode* pn)
{
MOZ_ASSERT(pn->isKind(ParseNodeKind::Call));
return ListHead(BinaryRight(pn));
return NextNode(ListHead(pn));
}
static inline ParseNode*
@ -615,16 +616,16 @@ static ParseNode*
DotBase(ParseNode* pn)
{
MOZ_ASSERT(pn->isKind(ParseNodeKind::Dot));
MOZ_ASSERT(pn->isArity(PN_BINARY));
return pn->pn_left;
MOZ_ASSERT(pn->isArity(PN_NAME));
return pn->expr();
}
static PropertyName*
DotMember(ParseNode* pn)
{
MOZ_ASSERT(pn->isKind(ParseNodeKind::Dot));
MOZ_ASSERT(pn->isArity(PN_BINARY));
return pn->pn_right->pn_atom->asPropertyName();
MOZ_ASSERT(pn->isArity(PN_NAME));
return pn->pn_atom->asPropertyName();
}
static ParseNode*
@ -2902,11 +2903,9 @@ IsArrayViewCtorName(ModuleValidator& m, PropertyName* name, Scalar::Type* type)
}
static bool
CheckNewArrayViewArgs(ModuleValidator& m, ParseNode* newExpr, PropertyName* bufferName)
CheckNewArrayViewArgs(ModuleValidator& m, ParseNode* ctorExpr, PropertyName* bufferName)
{
ParseNode* ctorExpr = BinaryLeft(newExpr);
ParseNode* ctorArgs = BinaryRight(newExpr);
ParseNode* bufArg = ListHead(ctorArgs);
ParseNode* bufArg = NextNode(ctorExpr);
if (!bufArg || NextNode(bufArg) != nullptr)
return m.fail(ctorExpr, "array view constructor takes exactly one argument");
@ -2927,7 +2926,7 @@ CheckNewArrayView(ModuleValidator& m, PropertyName* varName, ParseNode* newExpr)
if (!bufferName)
return m.fail(newExpr, "cannot create array view without an asm.js heap parameter");
ParseNode* ctorExpr = BinaryLeft(newExpr);
ParseNode* ctorExpr = ListHead(newExpr);
PropertyName* field;
Scalar::Type type;
@ -2956,7 +2955,7 @@ CheckNewArrayView(ModuleValidator& m, PropertyName* varName, ParseNode* newExpr)
type = global->viewType();
}
if (!CheckNewArrayViewArgs(m, newExpr, bufferName))
if (!CheckNewArrayViewArgs(m, ctorExpr, bufferName))
return false;
return m.addArrayView(varName, type, field);