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/SwitchEmitter.h"
9 #include "mozilla/Assertions.h" // MOZ_ASSERT
10 #include "mozilla/Span.h" // mozilla::Span
12 #include <algorithm> // std::min, std::max
14 #include "jstypes.h" // JS_BIT
16 #include "frontend/BytecodeEmitter.h" // BytecodeEmitter
17 #include "frontend/SharedContext.h" // StatementKind
18 #include "js/friend/ErrorMessages.h" // JSMSG_*
19 #include "js/TypeDecls.h" // jsbytecode
20 #include "util/BitArray.h"
21 #include "vm/BytecodeUtil.h" // SET_JUMP_OFFSET, JUMP_OFFSET_LEN, SET_RESUMEINDEX
22 #include "vm/Opcodes.h" // JSOp, JSOpLength_TableSwitch
23 #include "vm/Runtime.h" // ReportOutOfMemory
26 using namespace js::frontend
;
28 bool SwitchEmitter::TableGenerator::addNumber(int32_t caseValue
) {
33 if (unsigned(caseValue
+ int(Bit(15))) >= unsigned(Bit(16))) {
38 if (intmap_
.isNothing()) {
42 low_
= std::min(low_
, caseValue
);
43 high_
= std::max(high_
, caseValue
);
45 // Check for duplicates, which are not supported in a table switch.
46 // We bias caseValue by 65536 if it's negative, and hope that's a rare case
47 // (because it requires a malloc'd bitmap).
51 if (caseValue
>= intmapBitLength_
) {
52 size_t newLength
= NumWordsForBitArrayOfLength(caseValue
+ 1);
53 if (!intmap_
->resize(newLength
)) {
54 ReportOutOfMemory(bce_
->fc
);
57 intmapBitLength_
= newLength
* BitArrayElementBits
;
59 if (IsBitArrayElementSet(intmap_
->begin(), intmap_
->length(), caseValue
)) {
60 // Duplicate entry is not supported in table switch.
64 SetBitArrayElement(intmap_
->begin(), intmap_
->length(), caseValue
);
68 void SwitchEmitter::TableGenerator::finish(uint32_t caseCount
) {
85 // Compute table length. Don't use table switch if overlarge or more than
87 tableLength_
= uint32_t(high_
- low_
+ 1);
88 if (tableLength_
>= Bit(16) || tableLength_
> 2 * caseCount
) {
93 uint32_t SwitchEmitter::TableGenerator::toCaseIndex(int32_t caseValue
) const {
94 MOZ_ASSERT(finished_
);
95 MOZ_ASSERT(isValid());
96 uint32_t caseIndex
= uint32_t(caseValue
- low_
);
97 MOZ_ASSERT(caseIndex
< tableLength_
);
101 uint32_t SwitchEmitter::TableGenerator::tableLength() const {
102 MOZ_ASSERT(finished_
);
103 MOZ_ASSERT(isValid());
107 SwitchEmitter::SwitchEmitter(BytecodeEmitter
* bce
) : bce_(bce
) {}
109 bool SwitchEmitter::emitDiscriminant(uint32_t switchPos
) {
110 MOZ_ASSERT(state_
== State::Start
);
111 switchPos_
= switchPos
;
113 // Ensure that the column of the switch statement is set properly.
114 if (!bce_
->updateSourceCoordNotes(switchPos_
)) {
118 state_
= State::Discriminant
;
122 bool SwitchEmitter::emitLexical(LexicalScope::ParserData
* bindings
) {
123 MOZ_ASSERT(state_
== State::Discriminant
);
124 MOZ_ASSERT(bindings
);
126 tdzCacheLexical_
.emplace(bce_
);
127 emitterScope_
.emplace(bce_
);
128 if (!emitterScope_
->enterLexical(bce_
, ScopeKind::Lexical
, bindings
)) {
132 state_
= State::Lexical
;
136 bool SwitchEmitter::validateCaseCount(uint32_t caseCount
) {
137 MOZ_ASSERT(state_
== State::Discriminant
|| state_
== State::Lexical
);
138 if (caseCount
> Bit(16)) {
139 bce_
->reportError(switchPos_
, JSMSG_TOO_MANY_CASES
);
142 caseCount_
= caseCount
;
144 state_
= State::CaseCount
;
148 bool SwitchEmitter::emitCond() {
149 MOZ_ASSERT(state_
== State::CaseCount
);
153 // After entering the scope if necessary, push the switch control.
154 controlInfo_
.emplace(bce_
, StatementKind::Switch
);
155 top_
= bce_
->bytecodeSection().offset();
157 if (!caseOffsets_
.resize(caseCount_
)) {
158 ReportOutOfMemory(bce_
->fc
);
162 MOZ_ASSERT(top_
== bce_
->bytecodeSection().offset());
164 tdzCacheCaseAndBody_
.emplace(bce_
);
166 state_
= State::Cond
;
170 bool SwitchEmitter::emitTable(const TableGenerator
& tableGen
) {
171 MOZ_ASSERT(state_
== State::CaseCount
);
174 // After entering the scope if necessary, push the switch control.
175 controlInfo_
.emplace(bce_
, StatementKind::Switch
);
176 top_
= bce_
->bytecodeSection().offset();
178 if (!caseOffsets_
.resize(tableGen
.tableLength())) {
179 ReportOutOfMemory(bce_
->fc
);
183 MOZ_ASSERT(top_
== bce_
->bytecodeSection().offset());
184 if (!bce_
->emitN(JSOp::TableSwitch
,
185 JSOpLength_TableSwitch
- sizeof(jsbytecode
))) {
189 // Skip default offset.
191 bce_
->bytecodeSection().code(top_
+ BytecodeOffsetDiff(JUMP_OFFSET_LEN
));
193 // Fill in switch bounds, which we know fit in 16-bit offsets.
194 SET_JUMP_OFFSET(pc
, tableGen
.low());
195 SET_JUMP_OFFSET(pc
+ JUMP_OFFSET_LEN
, tableGen
.high());
197 state_
= State::Table
;
201 bool SwitchEmitter::emitCaseOrDefaultJump(uint32_t caseIndex
, bool isDefault
) {
202 MOZ_ASSERT(kind_
== Kind::Cond
);
205 if (!bce_
->emitJump(JSOp::Default
, &condSwitchDefaultOffset_
)) {
212 if (!bce_
->emitJump(JSOp::Case
, &caseJump
)) {
215 caseOffsets_
[caseIndex
] = caseJump
.offset
;
216 lastCaseOffset_
= caseJump
.offset
;
221 bool SwitchEmitter::prepareForCaseValue() {
222 MOZ_ASSERT(kind_
== Kind::Cond
);
223 MOZ_ASSERT(state_
== State::Cond
|| state_
== State::Case
);
225 if (!bce_
->emit1(JSOp::Dup
)) {
229 state_
= State::CaseValue
;
233 bool SwitchEmitter::emitCaseJump() {
234 MOZ_ASSERT(kind_
== Kind::Cond
);
235 MOZ_ASSERT(state_
== State::CaseValue
);
237 if (!bce_
->emit1(JSOp::StrictEq
)) {
241 if (!emitCaseOrDefaultJump(caseIndex_
, false)) {
246 state_
= State::Case
;
250 bool SwitchEmitter::emitImplicitDefault() {
251 MOZ_ASSERT(kind_
== Kind::Cond
);
252 MOZ_ASSERT(state_
== State::Cond
|| state_
== State::Case
);
253 if (!emitCaseOrDefaultJump(0, true)) {
259 // No internal state after emitting default jump.
263 bool SwitchEmitter::emitCaseBody() {
264 MOZ_ASSERT(kind_
== Kind::Cond
);
265 MOZ_ASSERT(state_
== State::Cond
|| state_
== State::Case
||
266 state_
== State::CaseBody
|| state_
== State::DefaultBody
);
268 tdzCacheCaseAndBody_
.reset();
270 if (state_
== State::Cond
|| state_
== State::Case
) {
271 // For cond switch, JSOp::Default is always emitted.
272 if (!emitImplicitDefault()) {
278 caseJump
.offset
= caseOffsets_
[caseIndex_
];
279 if (!bce_
->emitJumpTargetAndPatch(caseJump
)) {
284 if (!bce_
->emitJumpTarget(&here
)) {
289 tdzCacheCaseAndBody_
.emplace(bce_
);
291 state_
= State::CaseBody
;
295 bool SwitchEmitter::emitCaseBody(int32_t caseValue
,
296 const TableGenerator
& tableGen
) {
297 MOZ_ASSERT(kind_
== Kind::Table
);
298 MOZ_ASSERT(state_
== State::Table
|| state_
== State::CaseBody
||
299 state_
== State::DefaultBody
);
301 tdzCacheCaseAndBody_
.reset();
304 if (!bce_
->emitJumpTarget(&here
)) {
307 caseOffsets_
[tableGen
.toCaseIndex(caseValue
)] = here
.offset
;
309 tdzCacheCaseAndBody_
.emplace(bce_
);
311 state_
= State::CaseBody
;
315 bool SwitchEmitter::emitDefaultBody() {
316 MOZ_ASSERT(state_
== State::Cond
|| state_
== State::Table
||
317 state_
== State::Case
|| state_
== State::CaseBody
);
318 MOZ_ASSERT(!hasDefault_
);
320 tdzCacheCaseAndBody_
.reset();
322 if (state_
== State::Cond
|| state_
== State::Case
) {
323 // For cond switch, JSOp::Default is always emitted.
324 if (!emitImplicitDefault()) {
329 if (!bce_
->emitJumpTarget(&here
)) {
332 defaultJumpTargetOffset_
= here
;
334 tdzCacheCaseAndBody_
.emplace(bce_
);
337 state_
= State::DefaultBody
;
341 bool SwitchEmitter::emitEnd() {
342 MOZ_ASSERT(state_
== State::Cond
|| state_
== State::Table
||
343 state_
== State::CaseBody
|| state_
== State::DefaultBody
);
345 tdzCacheCaseAndBody_
.reset();
348 // If no default case, offset for default is to end of switch.
349 if (!bce_
->emitJumpTarget(&defaultJumpTargetOffset_
)) {
353 MOZ_ASSERT(defaultJumpTargetOffset_
.offset
.valid());
355 // Set the default offset (to end of switch if no default).
357 if (kind_
== Kind::Cond
) {
359 bce_
->patchJumpsToTarget(condSwitchDefaultOffset_
,
360 defaultJumpTargetOffset_
);
362 // Fill in the default jump target.
363 pc
= bce_
->bytecodeSection().code(top_
);
364 SET_JUMP_OFFSET(pc
, (defaultJumpTargetOffset_
.offset
- top_
).value());
365 pc
+= JUMP_OFFSET_LEN
;
368 if (kind_
== Kind::Table
) {
369 // Skip over the already-initialized switch bounds.
370 pc
+= 2 * JUMP_OFFSET_LEN
;
372 // Use the 'default' offset for missing cases.
373 for (uint32_t i
= 0, length
= caseOffsets_
.length(); i
< length
; i
++) {
374 if (caseOffsets_
[i
].value() == 0) {
375 caseOffsets_
[i
] = defaultJumpTargetOffset_
.offset
;
379 // Allocate resume index range.
380 uint32_t firstResumeIndex
= 0;
381 mozilla::Span
<BytecodeOffset
> offsets
=
382 mozilla::Span(caseOffsets_
.begin(), caseOffsets_
.end());
383 if (!bce_
->allocateResumeIndexRange(offsets
, &firstResumeIndex
)) {
386 SET_RESUMEINDEX(pc
, firstResumeIndex
);
389 // Patch breaks before leaving the scope, as all breaks are under the
390 // lexical scope if it exists.
391 if (!controlInfo_
->patchBreaks(bce_
)) {
395 if (emitterScope_
&& !emitterScope_
->leave(bce_
)) {
399 emitterScope_
.reset();
400 tdzCacheLexical_
.reset();
402 controlInfo_
.reset();
408 InternalSwitchEmitter::InternalSwitchEmitter(BytecodeEmitter
* bce
)
409 : SwitchEmitter(bce
) {
411 // Skip emitDiscriminant (see the comment above InternalSwitchEmitter)
412 state_
= State::Discriminant
;