Source code

Revision control

Other Tools

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/. */
6
7
#include "frontend/BytecodeControlStructures.h"
8
9
#include "frontend/BytecodeEmitter.h" // BytecodeEmitter
10
#include "frontend/EmitterScope.h" // EmitterScope
11
#include "vm/Opcodes.h" // JSOp
12
13
using namespace js;
14
using namespace js::frontend;
15
16
using mozilla::Maybe;
17
18
NestableControl::NestableControl(BytecodeEmitter* bce, StatementKind kind)
19
: Nestable<NestableControl>(&bce->innermostNestableControl),
20
kind_(kind),
21
emitterScope_(bce->innermostEmitterScopeNoCheck()) {}
22
23
BreakableControl::BreakableControl(BytecodeEmitter* bce, StatementKind kind)
24
: NestableControl(bce, kind) {
25
MOZ_ASSERT(is<BreakableControl>());
26
}
27
28
bool BreakableControl::patchBreaks(BytecodeEmitter* bce) {
29
return bce->emitJumpTargetAndPatch(breaks);
30
}
31
32
LabelControl::LabelControl(BytecodeEmitter* bce, JSAtom* label,
33
BytecodeOffset startOffset)
34
: BreakableControl(bce, StatementKind::Label),
35
label_(bce->cx, label),
36
startOffset_(startOffset) {}
37
38
LoopControl::LoopControl(BytecodeEmitter* bce, StatementKind loopKind)
39
: BreakableControl(bce, loopKind), tdzCache_(bce) {
40
MOZ_ASSERT(is<LoopControl>());
41
42
LoopControl* enclosingLoop = findNearest<LoopControl>(enclosing());
43
44
stackDepth_ = bce->bytecodeSection().stackDepth();
45
loopDepth_ = enclosingLoop ? enclosingLoop->loopDepth_ + 1 : 1;
46
}
47
48
bool LoopControl::emitContinueTarget(BytecodeEmitter* bce) {
49
// Note: this is always called after emitting the loop body so we must have
50
// emitted all 'continues' by now.
51
return bce->emitJumpTargetAndPatch(continues);
52
}
53
54
bool LoopControl::emitLoopHead(BytecodeEmitter* bce,
55
const Maybe<uint32_t>& nextPos) {
56
// Insert a Nop if needed to ensure the script does not start with a
57
// JSOp::LoopHead. This avoids JIT issues with prologue code + try notes
58
// or OSR. See bug 1602390 and bug 1602681.
59
if (bce->bytecodeSection().offset().toUint32() == 0) {
60
if (!bce->emit1(JSOp::Nop)) {
61
return false;
62
}
63
}
64
65
if (nextPos) {
66
if (!bce->updateSourceCoordNotes(*nextPos)) {
67
return false;
68
}
69
}
70
71
MOZ_ASSERT(loopDepth_ > 0);
72
73
head_ = {bce->bytecodeSection().offset()};
74
75
BytecodeOffset off;
76
if (!bce->emitJumpTargetOp(JSOp::LoopHead, &off)) {
77
return false;
78
}
79
SetLoopHeadDepthHint(bce->bytecodeSection().code(off), loopDepth_);
80
81
return true;
82
}
83
84
bool LoopControl::emitLoopEnd(BytecodeEmitter* bce, JSOp op,
85
TryNoteKind tryNoteKind) {
86
JumpList jump;
87
if (!bce->emitJumpNoFallthrough(op, &jump)) {
88
return false;
89
}
90
bce->patchJumpsToTarget(jump, head_);
91
92
// Create a fallthrough for closing iterators, and as a target for break
93
// statements.
94
JumpTarget breakTarget;
95
if (!bce->emitJumpTarget(&breakTarget)) {
96
return false;
97
}
98
if (!patchBreaks(bce)) {
99
return false;
100
}
101
if (!bce->addTryNote(tryNoteKind, bce->bytecodeSection().stackDepth(),
102
headOffset(), breakTarget.offset)) {
103
return false;
104
}
105
return true;
106
}
107
108
TryFinallyControl::TryFinallyControl(BytecodeEmitter* bce, StatementKind kind)
109
: NestableControl(bce, kind), emittingSubroutine_(false) {
110
MOZ_ASSERT(is<TryFinallyControl>());
111
}