1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * vim: set ts=8 sts=2 et sw=2 tw=80:
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "frontend/OptionalEmitter.h"
9 #include "frontend/BytecodeEmitter.h"
10 #include "frontend/IfEmitter.h" // IfEmitter, InternalIfEmitter, CondEmitter
11 #include "vm/Opcodes.h"
14 using namespace js::frontend
;
16 OptionalEmitter::OptionalEmitter(BytecodeEmitter
* bce
, int32_t initialDepth
)
17 : bce_(bce
), tdzCache_(bce
), initialDepth_(initialDepth
) {}
19 bool OptionalEmitter::emitJumpShortCircuit() {
20 MOZ_ASSERT(state_
== State::Start
|| state_
== State::ShortCircuit
||
21 state_
== State::ShortCircuitForCall
);
22 MOZ_ASSERT(initialDepth_
+ 1 == bce_
->bytecodeSection().stackDepth());
24 if (!bce_
->emit1(JSOp::IsNullOrUndefined
)) {
25 // [stack] OBJ NULL-OR-UNDEF
28 if (!bce_
->emitJump(JSOp::JumpIfTrue
, &jumpShortCircuit_
)) {
34 state_
= State::ShortCircuit
;
39 bool OptionalEmitter::emitJumpShortCircuitForCall() {
40 MOZ_ASSERT(state_
== State::Start
|| state_
== State::ShortCircuit
||
41 state_
== State::ShortCircuitForCall
);
42 int32_t depth
= bce_
->bytecodeSection().stackDepth();
43 MOZ_ASSERT(initialDepth_
+ 2 == depth
);
44 if (!bce_
->emit1(JSOp::Swap
)) {
45 // [stack] THIS CALLEE
49 InternalIfEmitter
ifEmitter(bce_
);
50 if (!bce_
->emit1(JSOp::IsNullOrUndefined
)) {
51 // [stack] THIS CALLEE NULL-OR-UNDEF
55 if (!ifEmitter
.emitThen()) {
56 // [stack] THIS CALLEE
60 if (!bce_
->emit1(JSOp::Pop
)) {
65 if (!bce_
->emitJump(JSOp::Goto
, &jumpShortCircuit_
)) {
70 if (!ifEmitter
.emitEnd()) {
74 bce_
->bytecodeSection().setStackDepth(depth
);
76 if (!bce_
->emit1(JSOp::Swap
)) {
77 // [stack] THIS CALLEE
81 state_
= State::ShortCircuitForCall
;
86 bool OptionalEmitter::emitOptionalJumpTarget(JSOp op
,
87 Kind kind
/* = Kind::Other */) {
89 int32_t depth
= bce_
->bytecodeSection().stackDepth();
91 MOZ_ASSERT(state_
== State::ShortCircuit
||
92 state_
== State::ShortCircuitForCall
);
94 // if we get to this point, it means that the optional chain did not short
95 // circuit, so we should skip the short circuiting bytecode.
96 if (!bce_
->emitJump(JSOp::Goto
, &jumpFinish_
)) {
101 if (!bce_
->emitJumpTargetAndPatch(jumpShortCircuit_
)) {
104 // [stack] # otherwise
109 // reset stack depth to the depth when we jumped
110 bce_
->bytecodeSection().setStackDepth(initialDepth_
+ 1);
112 if (!bce_
->emit1(JSOp::Pop
)) {
117 if (!bce_
->emit1(op
)) {
122 if (kind
== Kind::Reference
) {
123 if (!bce_
->emit1(op
)) {
129 MOZ_ASSERT(depth
== bce_
->bytecodeSection().stackDepth());
131 if (!bce_
->emitJumpTargetAndPatch(jumpFinish_
)) {
133 // [stack] CALLEE THIS
134 // [stack] # otherwise
139 state_
= State::JumpEnd
;