mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-18 07:45:30 +00:00
Bug 1662559 - Part 17: Change BytecodeEmitter to use the new PrivateOpEmitter class. r=arai
Depends on D108298 Differential Revision: https://phabricator.services.mozilla.com/D108299
This commit is contained in:
parent
10dffc1a2e
commit
af06f97c61
@ -49,12 +49,13 @@
|
||||
#include "frontend/NameOpEmitter.h" // NameOpEmitter
|
||||
#include "frontend/ObjectEmitter.h" // PropertyEmitter, ObjectEmitter, ClassEmitter
|
||||
#include "frontend/OptionalEmitter.h" // OptionalEmitter
|
||||
#include "frontend/ParseNode.h" // ParseNodeKind, ParseNode and subclasses
|
||||
#include "frontend/Parser.h" // Parser
|
||||
#include "frontend/ParserAtom.h" // ParserAtomsTable
|
||||
#include "frontend/PropOpEmitter.h" // PropOpEmitter
|
||||
#include "frontend/SourceNotes.h" // SrcNote, SrcNoteType, SrcNoteWriter
|
||||
#include "frontend/SwitchEmitter.h" // SwitchEmitter
|
||||
#include "frontend/ParseNode.h" // ParseNodeKind, ParseNode and subclasses
|
||||
#include "frontend/Parser.h" // Parser
|
||||
#include "frontend/ParserAtom.h" // ParserAtomsTable
|
||||
#include "frontend/PrivateOpEmitter.h" // PrivateOpEmitter
|
||||
#include "frontend/PropOpEmitter.h" // PropOpEmitter
|
||||
#include "frontend/SourceNotes.h" // SrcNote, SrcNoteType, SrcNoteWriter
|
||||
#include "frontend/SwitchEmitter.h" // SwitchEmitter
|
||||
#include "frontend/TaggedParserAtomIndexHasher.h" // TaggedParserAtomIndexHasher
|
||||
#include "frontend/TDZCheckCache.h" // TDZCheckCache
|
||||
#include "frontend/TryEmitter.h" // TryEmitter
|
||||
@ -2091,14 +2092,17 @@ bool BytecodeEmitter::emitCallIncDec(UnaryNode* incDec) {
|
||||
bool BytecodeEmitter::emitPrivateIncDec(UnaryNode* incDec) {
|
||||
PrivateMemberAccess* privateExpr = &incDec->kid()->as<PrivateMemberAccess>();
|
||||
ParseNodeKind kind = incDec->getKind();
|
||||
ElemOpEmitter eoe(this, ConvertIncDecKind(kind),
|
||||
ElemOpEmitter::ObjKind::Other, NameVisibility::Private);
|
||||
if (!emitObjAndKey(&privateExpr->expression(), &privateExpr->privateName(),
|
||||
eoe)) {
|
||||
// [stack] OBJ KEY
|
||||
PrivateOpEmitter xoe(this, ConvertIncDecKind(kind),
|
||||
privateExpr->privateName().name());
|
||||
if (!emitTree(&privateExpr->expression())) {
|
||||
// [stack] OBJ
|
||||
return false;
|
||||
}
|
||||
if (!eoe.emitIncDec()) {
|
||||
if (!xoe.emitReference()) {
|
||||
// [stack] OBJ NAME
|
||||
return false;
|
||||
}
|
||||
if (!xoe.emitIncDec()) {
|
||||
// [stack] RESULT
|
||||
return false;
|
||||
}
|
||||
@ -2848,18 +2852,17 @@ bool BytecodeEmitter::emitDestructuringLHSRef(ParseNode* target,
|
||||
|
||||
case ParseNodeKind::PrivateMemberExpr: {
|
||||
PrivateMemberAccess* privateExpr = &target->as<PrivateMemberAccess>();
|
||||
ElemOpEmitter eoe(this, ElemOpEmitter::Kind::SimpleAssignment,
|
||||
ElemOpEmitter::ObjKind::Other, NameVisibility::Private);
|
||||
if (!emitObjAndKey(&privateExpr->expression(),
|
||||
&privateExpr->privateName(), eoe)) {
|
||||
// [stack] OBJ KEY
|
||||
PrivateOpEmitter xoe(this, PrivateOpEmitter::Kind::SimpleAssignment,
|
||||
privateExpr->privateName().name());
|
||||
if (!emitTree(&privateExpr->expression())) {
|
||||
// [stack] OBJ
|
||||
return false;
|
||||
}
|
||||
*emitted = 2;
|
||||
if (!eoe.prepareForRhs()) {
|
||||
// [stack] OBJ KEY
|
||||
if (!xoe.emitReference()) {
|
||||
// [stack] OBJ NAME
|
||||
return false;
|
||||
}
|
||||
*emitted = xoe.numReferenceSlots();
|
||||
break;
|
||||
}
|
||||
|
||||
@ -2996,13 +2999,14 @@ bool BytecodeEmitter::emitSetOrInitializeDestructuring(
|
||||
|
||||
case ParseNodeKind::PrivateMemberExpr: {
|
||||
// The reference is already pushed by emitDestructuringLHSRef.
|
||||
// [stack] OBJ KEY VAL
|
||||
ElemOpEmitter eoe(this, ElemOpEmitter::Kind::SimpleAssignment,
|
||||
ElemOpEmitter::ObjKind::Other, NameVisibility::Private);
|
||||
if (!eoe.skipObjAndKeyAndRhs()) {
|
||||
// [stack] OBJ NAME VAL
|
||||
PrivateMemberAccess* privateExpr = &target->as<PrivateMemberAccess>();
|
||||
PrivateOpEmitter xoe(this, PrivateOpEmitter::Kind::SimpleAssignment,
|
||||
privateExpr->privateName().name());
|
||||
if (!xoe.skipReference()) {
|
||||
return false;
|
||||
}
|
||||
if (!eoe.emitAssignment()) {
|
||||
if (!xoe.emitAssignment()) {
|
||||
// [stack] VAL
|
||||
return false;
|
||||
}
|
||||
@ -4357,6 +4361,7 @@ bool BytecodeEmitter::emitAssignmentOrInit(ParseNodeKind kind, ParseNode* lhs,
|
||||
Maybe<NameOpEmitter> noe;
|
||||
Maybe<PropOpEmitter> poe;
|
||||
Maybe<ElemOpEmitter> eoe;
|
||||
Maybe<PrivateOpEmitter> xoe;
|
||||
|
||||
// Deal with non-name assignments.
|
||||
uint8_t offset = 1;
|
||||
@ -4442,17 +4447,20 @@ bool BytecodeEmitter::emitAssignmentOrInit(ParseNodeKind kind, ParseNode* lhs,
|
||||
}
|
||||
case ParseNodeKind::PrivateMemberExpr: {
|
||||
PrivateMemberAccess* privateExpr = &lhs->as<PrivateMemberAccess>();
|
||||
eoe.emplace(this,
|
||||
isCompound ? ElemOpEmitter::Kind::CompoundAssignment
|
||||
: isInit ? ElemOpEmitter::Kind::PropInit
|
||||
: ElemOpEmitter::Kind::SimpleAssignment,
|
||||
ElemOpEmitter::ObjKind::Other, NameVisibility::Private);
|
||||
if (!emitObjAndKey(&privateExpr->expression(),
|
||||
&privateExpr->privateName(), *eoe)) {
|
||||
xoe.emplace(this,
|
||||
isCompound ? PrivateOpEmitter::Kind::CompoundAssignment
|
||||
: isInit ? PrivateOpEmitter::Kind::PropInit
|
||||
: PrivateOpEmitter::Kind::SimpleAssignment,
|
||||
privateExpr->privateName().name());
|
||||
if (!emitTree(&privateExpr->expression())) {
|
||||
// [stack] OBJ
|
||||
return false;
|
||||
}
|
||||
if (!xoe->emitReference()) {
|
||||
// [stack] OBJ KEY
|
||||
return false;
|
||||
}
|
||||
offset += 2;
|
||||
offset += xoe->numReferenceSlots();
|
||||
break;
|
||||
}
|
||||
case ParseNodeKind::ArrayExpr:
|
||||
@ -4492,14 +4500,20 @@ bool BytecodeEmitter::emitAssignmentOrInit(ParseNodeKind kind, ParseNode* lhs,
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ParseNodeKind::ElemExpr:
|
||||
case ParseNodeKind::PrivateMemberExpr: {
|
||||
case ParseNodeKind::ElemExpr: {
|
||||
if (!eoe->emitGet()) {
|
||||
// [stack] KEY THIS OBJ ELEM
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ParseNodeKind::PrivateMemberExpr: {
|
||||
if (!xoe->emitGet()) {
|
||||
// [stack] OBJ KEY VALUE
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ParseNodeKind::CallExpr:
|
||||
// We just emitted a JSOp::ThrowMsg and popped the call's return
|
||||
// value. Push a random value to make sure the stack depth is
|
||||
@ -4535,7 +4549,6 @@ bool BytecodeEmitter::emitAssignmentOrInit(ParseNodeKind kind, ParseNode* lhs,
|
||||
}
|
||||
break;
|
||||
case ParseNodeKind::ElemExpr:
|
||||
case ParseNodeKind::PrivateMemberExpr:
|
||||
if (!eoe->prepareForRhs()) {
|
||||
// [stack] # if Simple Assignment with Super
|
||||
// [stack] THIS KEY SUPERBASE
|
||||
@ -4548,6 +4561,9 @@ bool BytecodeEmitter::emitAssignmentOrInit(ParseNodeKind kind, ParseNode* lhs,
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case ParseNodeKind::PrivateMemberExpr:
|
||||
// no stack adjustment needed
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -4596,14 +4612,19 @@ bool BytecodeEmitter::emitAssignmentOrInit(ParseNodeKind kind, ParseNode* lhs,
|
||||
case ParseNodeKind::CallExpr:
|
||||
// We threw above, so nothing to do here.
|
||||
break;
|
||||
case ParseNodeKind::ElemExpr:
|
||||
case ParseNodeKind::PrivateMemberExpr: {
|
||||
case ParseNodeKind::ElemExpr: {
|
||||
if (!eoe->emitAssignment()) {
|
||||
// [stack] VAL
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ParseNodeKind::PrivateMemberExpr:
|
||||
if (!xoe->emitAssignment()) {
|
||||
// [stack] VAL
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case ParseNodeKind::ArrayExpr:
|
||||
case ParseNodeKind::ObjectExpr:
|
||||
if (!emitDestructuringOps(&lhs->as<ListNode>(),
|
||||
@ -4645,6 +4666,7 @@ bool BytecodeEmitter::emitShortCircuitAssignment(AssignmentNode* node) {
|
||||
Maybe<NameOpEmitter> noe;
|
||||
Maybe<PropOpEmitter> poe;
|
||||
Maybe<ElemOpEmitter> eoe;
|
||||
Maybe<PrivateOpEmitter> xoe;
|
||||
|
||||
int32_t depth = bytecodeSection().stackDepth();
|
||||
|
||||
@ -4751,24 +4773,21 @@ bool BytecodeEmitter::emitShortCircuitAssignment(AssignmentNode* node) {
|
||||
|
||||
case ParseNodeKind::PrivateMemberExpr: {
|
||||
PrivateMemberAccess* privateExpr = &lhs->as<PrivateMemberAccess>();
|
||||
eoe.emplace(this, ElemOpEmitter::Kind::CompoundAssignment,
|
||||
ElemOpEmitter::ObjKind::Other, NameVisibility::Private);
|
||||
|
||||
if (!emitObjAndKey(&privateExpr->expression(),
|
||||
&privateExpr->privateName(), *eoe)) {
|
||||
// [stack] OBJ KEY
|
||||
xoe.emplace(this, PrivateOpEmitter::Kind::CompoundAssignment,
|
||||
privateExpr->privateName().name());
|
||||
if (!emitTree(&privateExpr->expression())) {
|
||||
// [stack] OBJ
|
||||
return false;
|
||||
}
|
||||
if (!eoe->emitGet()) {
|
||||
// [stack] OBJ KEY LHS
|
||||
if (!xoe->emitReference()) {
|
||||
// [stack] OBJ NAME
|
||||
return false;
|
||||
}
|
||||
if (!eoe->prepareForRhs()) {
|
||||
// [stack] OBJ KEY LHS
|
||||
if (!xoe->emitGet()) {
|
||||
// [stack] OBJ NAME LHS
|
||||
return false;
|
||||
}
|
||||
|
||||
numPushed = 2;
|
||||
numPushed = xoe->numReferenceSlots();
|
||||
break;
|
||||
}
|
||||
|
||||
@ -4817,8 +4836,7 @@ bool BytecodeEmitter::emitShortCircuitAssignment(AssignmentNode* node) {
|
||||
break;
|
||||
}
|
||||
|
||||
case ParseNodeKind::ElemExpr:
|
||||
case ParseNodeKind::PrivateMemberExpr: {
|
||||
case ParseNodeKind::ElemExpr: {
|
||||
if (!eoe->emitAssignment()) {
|
||||
// [stack] RHS
|
||||
return false;
|
||||
@ -4826,6 +4844,13 @@ bool BytecodeEmitter::emitShortCircuitAssignment(AssignmentNode* node) {
|
||||
break;
|
||||
}
|
||||
|
||||
case ParseNodeKind::PrivateMemberExpr:
|
||||
if (!xoe->emitAssignment()) {
|
||||
// [stack] RHS
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
MOZ_CRASH();
|
||||
}
|
||||
@ -7796,8 +7821,8 @@ bool BytecodeEmitter::emitOptionalCalleeAndThis(ParseNode* callee,
|
||||
case ParseNodeKind::OptionalElemExpr: {
|
||||
OptionalPropertyByValue* elem = &callee->as<OptionalPropertyByValue>();
|
||||
bool isSuper = false;
|
||||
bool isPrivate = elem->key().isKind(ParseNodeKind::PrivateName);
|
||||
ElemOpEmitter& eoe = cone.prepareForElemCallee(isSuper, isPrivate);
|
||||
MOZ_ASSERT(!elem->key().isKind(ParseNodeKind::PrivateName));
|
||||
ElemOpEmitter& eoe = cone.prepareForElemCallee(isSuper);
|
||||
if (!emitOptionalElemExpression(elem, eoe, isSuper, oe)) {
|
||||
// [stack] CALLEE THIS
|
||||
return false;
|
||||
@ -7807,8 +7832,8 @@ bool BytecodeEmitter::emitOptionalCalleeAndThis(ParseNode* callee,
|
||||
case ParseNodeKind::ElemExpr: {
|
||||
PropertyByValue* elem = &callee->as<PropertyByValue>();
|
||||
bool isSuper = elem->isSuper();
|
||||
bool isPrivate = elem->key().isKind(ParseNodeKind::PrivateName);
|
||||
ElemOpEmitter& eoe = cone.prepareForElemCallee(isSuper, isPrivate);
|
||||
MOZ_ASSERT(!elem->key().isKind(ParseNodeKind::PrivateName));
|
||||
ElemOpEmitter& eoe = cone.prepareForElemCallee(isSuper);
|
||||
if (!emitOptionalElemExpression(elem, eoe, isSuper, oe)) {
|
||||
// [stack] CALLEE THIS
|
||||
return false;
|
||||
@ -7820,10 +7845,9 @@ bool BytecodeEmitter::emitOptionalCalleeAndThis(ParseNode* callee,
|
||||
case ParseNodeKind::OptionalPrivateMemberExpr: {
|
||||
PrivateMemberAccessBase* privateExpr =
|
||||
&callee->as<PrivateMemberAccessBase>();
|
||||
bool isSuper = false;
|
||||
bool isPrivate = true;
|
||||
ElemOpEmitter& eoe = cone.prepareForElemCallee(isSuper, isPrivate);
|
||||
if (!emitOptionalPrivateExpression(privateExpr, eoe, oe)) {
|
||||
PrivateOpEmitter& xoe =
|
||||
cone.prepareForPrivateCallee(privateExpr->privateName().name());
|
||||
if (!emitOptionalPrivateExpression(privateExpr, xoe, oe)) {
|
||||
// [stack] CALLEE THIS
|
||||
return false;
|
||||
}
|
||||
@ -7909,8 +7933,8 @@ bool BytecodeEmitter::emitCalleeAndThis(ParseNode* callee, ParseNode* call,
|
||||
MOZ_ASSERT(emitterMode != BytecodeEmitter::SelfHosting);
|
||||
PropertyByValue* elem = &callee->as<PropertyByValue>();
|
||||
bool isSuper = elem->isSuper();
|
||||
bool isPrivate = elem->key().isKind(ParseNodeKind::PrivateName);
|
||||
ElemOpEmitter& eoe = cone.prepareForElemCallee(isSuper, isPrivate);
|
||||
MOZ_ASSERT(!elem->key().isKind(ParseNodeKind::PrivateName));
|
||||
ElemOpEmitter& eoe = cone.prepareForElemCallee(isSuper);
|
||||
if (!emitElemObjAndKey(elem, isSuper, eoe)) {
|
||||
// [stack] # if Super
|
||||
// [stack] THIS? THIS KEY
|
||||
@ -7929,16 +7953,18 @@ bool BytecodeEmitter::emitCalleeAndThis(ParseNode* callee, ParseNode* call,
|
||||
MOZ_ASSERT(emitterMode != BytecodeEmitter::SelfHosting);
|
||||
PrivateMemberAccessBase* privateExpr =
|
||||
&callee->as<PrivateMemberAccessBase>();
|
||||
bool isSuper = false;
|
||||
bool isPrivate = true;
|
||||
ElemOpEmitter& eoe = cone.prepareForElemCallee(isSuper, isPrivate);
|
||||
if (!emitObjAndKey(&privateExpr->expression(),
|
||||
&privateExpr->privateName(), eoe)) {
|
||||
// [stack] OBJ? OBJ KEY
|
||||
PrivateOpEmitter& xoe =
|
||||
cone.prepareForPrivateCallee(privateExpr->privateName().name());
|
||||
if (!emitTree(&privateExpr->expression())) {
|
||||
// [stack] OBJ
|
||||
return false;
|
||||
}
|
||||
if (!eoe.emitGet()) {
|
||||
// [stack] CALLEE THIS?
|
||||
if (!xoe.emitReference()) {
|
||||
// [stack] OBJ NAME
|
||||
return false;
|
||||
}
|
||||
if (!xoe.emitGetForCallOrNew()) {
|
||||
// [stack] CALLEE THIS
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -8418,9 +8444,9 @@ bool BytecodeEmitter::emitOptionalTree(
|
||||
case ParseNodeKind::PrivateMemberExpr:
|
||||
case ParseNodeKind::OptionalPrivateMemberExpr: {
|
||||
PrivateMemberAccessBase* privateExpr = &pn->as<PrivateMemberAccessBase>();
|
||||
ElemOpEmitter eoe(this, ElemOpEmitter::Kind::Get,
|
||||
ElemOpEmitter::ObjKind::Other, NameVisibility::Private);
|
||||
if (!emitOptionalPrivateExpression(privateExpr, eoe, oe)) {
|
||||
PrivateOpEmitter xoe(this, PrivateOpEmitter::Kind::Get,
|
||||
privateExpr->privateName().name());
|
||||
if (!emitOptionalPrivateExpression(privateExpr, xoe, oe)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
@ -8617,13 +8643,8 @@ bool BytecodeEmitter::emitOptionalElemExpression(PropertyByValueBase* elem,
|
||||
}
|
||||
|
||||
bool BytecodeEmitter::emitOptionalPrivateExpression(
|
||||
PrivateMemberAccessBase* privateExpr, ElemOpEmitter& eoe,
|
||||
PrivateMemberAccessBase* privateExpr, PrivateOpEmitter& xoe,
|
||||
OptionalEmitter& oe) {
|
||||
if (!eoe.prepareForObj()) {
|
||||
// [stack]
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!emitOptionalTree(&privateExpr->expression(), oe)) {
|
||||
// [stack] OBJ
|
||||
return false;
|
||||
@ -8639,18 +8660,13 @@ bool BytecodeEmitter::emitOptionalPrivateExpression(
|
||||
}
|
||||
}
|
||||
|
||||
if (!eoe.prepareForKey()) {
|
||||
// [stack] OBJ? OBJ
|
||||
if (!xoe.emitReference()) {
|
||||
// [stack] OBJ NAME
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!emitTree(&privateExpr->privateName())) {
|
||||
// [stack] OBJ? OBJ KEY
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!eoe.emitGet()) {
|
||||
// [stack] ELEM
|
||||
if (!xoe.emitGet()) {
|
||||
// [stack] CALLEE THIS # if call
|
||||
// [stack] VALUE # otherwise
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -11362,14 +11378,17 @@ bool BytecodeEmitter::emitTree(
|
||||
|
||||
case ParseNodeKind::PrivateMemberExpr: {
|
||||
PrivateMemberAccess* privateExpr = &pn->as<PrivateMemberAccess>();
|
||||
ElemOpEmitter eoe(this, ElemOpEmitter::Kind::Get,
|
||||
ElemOpEmitter::ObjKind::Other, NameVisibility::Private);
|
||||
if (!emitObjAndKey(&privateExpr->expression(),
|
||||
&privateExpr->privateName(), eoe)) {
|
||||
// [stack] OBJ KEY
|
||||
PrivateOpEmitter xoe(this, PrivateOpEmitter::Kind::Get,
|
||||
privateExpr->privateName().name());
|
||||
if (!emitTree(&privateExpr->expression())) {
|
||||
// [stack] OBJ
|
||||
return false;
|
||||
}
|
||||
if (!eoe.emitGet()) {
|
||||
if (!xoe.emitReference()) {
|
||||
// [stack] OBJ NAME
|
||||
return false;
|
||||
}
|
||||
if (!xoe.emitGet()) {
|
||||
// [stack] VALUE
|
||||
return false;
|
||||
}
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include "frontend/ParseNode.h" // ParseNode and subclasses
|
||||
#include "frontend/Parser.h" // Parser, PropListType
|
||||
#include "frontend/ParserAtom.h" // TaggedParserAtomIndex
|
||||
#include "frontend/PrivateOpEmitter.h" // PrivateOpEmitter
|
||||
#include "frontend/ScriptIndex.h" // ScriptIndex
|
||||
#include "frontend/SharedContext.h" // SharedContext, TopLevelFunction
|
||||
#include "frontend/SourceNotes.h" // SrcNoteType
|
||||
@ -763,7 +764,7 @@ struct MOZ_STACK_CLASS BytecodeEmitter {
|
||||
bool isSuper,
|
||||
OptionalEmitter& oe);
|
||||
[[nodiscard]] bool emitOptionalPrivateExpression(
|
||||
PrivateMemberAccessBase* privateExpr, ElemOpEmitter& eoe,
|
||||
PrivateMemberAccessBase* privateExpr, PrivateOpEmitter& xoe,
|
||||
OptionalEmitter& oe);
|
||||
[[nodiscard]] bool emitOptionalCall(CallNode* callNode, OptionalEmitter& oe,
|
||||
ValueUsage valueUsage);
|
||||
|
@ -57,19 +57,30 @@ bool CallOrNewEmitter::emitNameCallee(TaggedParserAtomIndex name) {
|
||||
}
|
||||
|
||||
[[nodiscard]] ElemOpEmitter& CallOrNewEmitter::prepareForElemCallee(
|
||||
bool isSuperElem, bool isPrivate) {
|
||||
bool isSuperElem) {
|
||||
MOZ_ASSERT(state_ == State::Start);
|
||||
|
||||
eoe_.emplace(bce_,
|
||||
isCall() ? ElemOpEmitter::Kind::Call : ElemOpEmitter::Kind::Get,
|
||||
isSuperElem ? ElemOpEmitter::ObjKind::Super
|
||||
: ElemOpEmitter::ObjKind::Other,
|
||||
isPrivate ? NameVisibility::Private : NameVisibility::Public);
|
||||
NameVisibility::Public);
|
||||
|
||||
state_ = State::ElemCallee;
|
||||
return *eoe_;
|
||||
}
|
||||
|
||||
PrivateOpEmitter& CallOrNewEmitter::prepareForPrivateCallee(
|
||||
TaggedParserAtomIndex privateName) {
|
||||
MOZ_ASSERT(state_ == State::Start);
|
||||
xoe_.emplace(
|
||||
bce_,
|
||||
isCall() ? PrivateOpEmitter::Kind::Call : PrivateOpEmitter::Kind::Get,
|
||||
privateName);
|
||||
state_ = State::PrivateCallee;
|
||||
return *xoe_;
|
||||
}
|
||||
|
||||
bool CallOrNewEmitter::prepareForFunctionCallee() {
|
||||
MOZ_ASSERT(state_ == State::Start);
|
||||
|
||||
@ -106,8 +117,9 @@ bool CallOrNewEmitter::prepareForOtherCallee() {
|
||||
|
||||
bool CallOrNewEmitter::emitThis() {
|
||||
MOZ_ASSERT(state_ == State::NameCallee || state_ == State::PropCallee ||
|
||||
state_ == State::ElemCallee || state_ == State::FunctionCallee ||
|
||||
state_ == State::SuperCallee || state_ == State::OtherCallee);
|
||||
state_ == State::ElemCallee || state_ == State::PrivateCallee ||
|
||||
state_ == State::FunctionCallee || state_ == State::SuperCallee ||
|
||||
state_ == State::OtherCallee);
|
||||
|
||||
bool needsThis = false;
|
||||
switch (state_) {
|
||||
@ -128,6 +140,12 @@ bool CallOrNewEmitter::emitThis() {
|
||||
needsThis = true;
|
||||
}
|
||||
break;
|
||||
case State::PrivateCallee:
|
||||
xoe_.reset();
|
||||
if (!isCall()) {
|
||||
needsThis = true;
|
||||
}
|
||||
break;
|
||||
case State::FunctionCallee:
|
||||
needsThis = true;
|
||||
break;
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "frontend/ElemOpEmitter.h"
|
||||
#include "frontend/IfEmitter.h"
|
||||
#include "frontend/ParserAtom.h" // TaggedParserAtomIndex
|
||||
#include "frontend/PrivateOpEmitter.h"
|
||||
#include "frontend/PropOpEmitter.h"
|
||||
#include "frontend/ValueUsage.h"
|
||||
#include "js/TypeDecls.h"
|
||||
@ -63,6 +64,16 @@ struct BytecodeEmitter;
|
||||
// emit(arg);
|
||||
// cone.emitEnd(1, Some(offset_of_callee));
|
||||
//
|
||||
// `callee.#method(arg);`
|
||||
// CallOrNewEmitter cone(this, JSOp::Call,
|
||||
// CallOrNewEmitter::ArgumentsKind::Other,
|
||||
// ValueUsage::WantValue);
|
||||
// PrivateOpEmitter& xoe = cone.prepareForPrivateCallee();
|
||||
// ... emit `callee.#method` with `xoe` here...
|
||||
// cone.prepareForNonSpreadArguments();
|
||||
// emit(arg);
|
||||
// cone.emitEnd(1, Some(offset_of_callee));
|
||||
//
|
||||
// `(function() { ... })(arg);`
|
||||
// CallOrNewEmitter cone(this, JSOp::Call,
|
||||
// CallOrNewEmitter::ArgumentsKind::Other,
|
||||
@ -159,6 +170,7 @@ class MOZ_STACK_CLASS CallOrNewEmitter {
|
||||
|
||||
mozilla::Maybe<PropOpEmitter> poe_;
|
||||
mozilla::Maybe<ElemOpEmitter> eoe_;
|
||||
mozilla::Maybe<PrivateOpEmitter> xoe_;
|
||||
|
||||
// The state of this emitter.
|
||||
//
|
||||
@ -174,6 +186,10 @@ class MOZ_STACK_CLASS CallOrNewEmitter {
|
||||
// +------------------------->| ElemCallee |----->+
|
||||
// | +------------+ |
|
||||
// | |
|
||||
// | prepareForPrivateCallee +---------------+ v
|
||||
// +------------------------->| PrivateCallee |-->+
|
||||
// | +---------------+ |
|
||||
// | |
|
||||
// | prepareForFunctionCallee +----------------+ v
|
||||
// +------------------------->| FunctionCallee |->+
|
||||
// | +----------------+ |
|
||||
@ -221,6 +237,9 @@ class MOZ_STACK_CLASS CallOrNewEmitter {
|
||||
// After calling prepareForElemCallee.
|
||||
ElemCallee,
|
||||
|
||||
// After calling prepareForPrivateCallee.
|
||||
PrivateCallee,
|
||||
|
||||
// After calling prepareForFunctionCallee.
|
||||
FunctionCallee,
|
||||
|
||||
@ -287,8 +306,9 @@ class MOZ_STACK_CLASS CallOrNewEmitter {
|
||||
public:
|
||||
[[nodiscard]] bool emitNameCallee(TaggedParserAtomIndex name);
|
||||
[[nodiscard]] PropOpEmitter& prepareForPropCallee(bool isSuperProp);
|
||||
[[nodiscard]] ElemOpEmitter& prepareForElemCallee(bool isSuperElem,
|
||||
bool isPrivateElem);
|
||||
[[nodiscard]] ElemOpEmitter& prepareForElemCallee(bool isSuperElem);
|
||||
[[nodiscard]] PrivateOpEmitter& prepareForPrivateCallee(
|
||||
TaggedParserAtomIndex privateName);
|
||||
[[nodiscard]] bool prepareForFunctionCallee();
|
||||
[[nodiscard]] bool emitSuperCallee();
|
||||
[[nodiscard]] bool prepareForOtherCallee();
|
||||
|
@ -149,8 +149,16 @@ bool PrivateOpEmitter::emitGet() {
|
||||
// [stack] OBJ? OBJ NAME
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isCompoundAssignment()) {
|
||||
if (!bce_->emit1(JSOp::Dup2)) {
|
||||
// [stack] OBJ? OBJ NAME OBJ NAME
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!bce_->emitElemOpBase(JSOp::GetElem, ShouldInstrument::Yes)) {
|
||||
// [stack] OBJ? VALUE
|
||||
// [stack] OBJ? OBJ NAME VALUE
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,16 @@ class B {
|
||||
return 12;
|
||||
}
|
||||
|
||||
#privF = () => { return 12; }
|
||||
|
||||
callPriv() {
|
||||
return this.#priv();
|
||||
}
|
||||
|
||||
callPrivF() {
|
||||
return this.#privF();
|
||||
}
|
||||
|
||||
#val = '';
|
||||
set #x(x) {
|
||||
this.#val = x + ' haha';
|
||||
@ -18,8 +28,23 @@ class B {
|
||||
ef(str) {
|
||||
return evalInFrame(0, str);
|
||||
}
|
||||
|
||||
callFunc(f) {
|
||||
f();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var b = new B();
|
||||
assertEq(b.ef(`this.#priv();`), 12);
|
||||
assertEq(b.ef(`this.#x = 'Hi'; this.#x`), 'Hi haha');
|
||||
|
||||
assertEq(b.ef("this.callPriv()"), 12);
|
||||
assertEq(b.ef("this.callPrivF()"), 12);
|
||||
assertThrowsInstanceOf(() => b.ef(`this.callFunc(() => { this.#privF(); })`), Error);
|
||||
|
||||
// See EmitterScope::lookupPrivate for the reasoning here.
|
||||
assertThrowsInstanceOf(() => b.ef(`this.#privF();`), Error);
|
||||
assertThrowsInstanceOf(() => b.ef(`var x = () => { return this.#privF(); } x();`), Error);
|
||||
assertThrowsInstanceOf(() => b.ef(`this.#priv();`), Error);
|
||||
assertThrowsInstanceOf(() => b.ef(`var x = () => { return this.#priv(); } x();`), Error);
|
||||
assertThrowsInstanceOf(() => b.ef(`this.#x = 'Hi'; this.#x`), Error);
|
||||
assertThrowsInstanceOf(() => b.ef(`var x = () => { this.#x = 'Hi'; return this.#x} x();`), Error);
|
||||
|
@ -12,4 +12,4 @@ class B {
|
||||
|
||||
var b = new B();
|
||||
assertEq(b.ef(`this.x`), 'his');
|
||||
assertEq(b.ef(`this.#x`), 12);
|
||||
assertThrowsInstanceOf(() => b.ef(`this.#x`), Error);
|
@ -17,6 +17,15 @@ class A {
|
||||
return o?.#x;
|
||||
}
|
||||
|
||||
static orEqual(o, v) {
|
||||
o.#x ||= v;
|
||||
return o.#x;
|
||||
}
|
||||
|
||||
setX(v) {
|
||||
this.#x = v;
|
||||
}
|
||||
|
||||
compoundInc() {
|
||||
this.#x += 1;
|
||||
return this.#x;
|
||||
@ -65,6 +74,9 @@ for (var i = 0; i < 1000; i++) {
|
||||
assertEq(a.x(), 11);
|
||||
assertEq(A.readx(a), 11);
|
||||
assertEq(a.compoundInc(), 12);
|
||||
assertEq(A.orEqual(a, 13), 12);
|
||||
a.setX(null);
|
||||
assertEq(A.orEqual(a, 12), 12);
|
||||
assertEq(a.compoundDec(), 11);
|
||||
assertEq(a.invoke(), 'hi');
|
||||
assertEq(a.gz(), 'static');
|
||||
|
Loading…
Reference in New Issue
Block a user