summaryrefslogtreecommitdiffstats
path: root/js/src/frontend/ForOfLoopControl.h
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/frontend/ForOfLoopControl.h')
-rw-r--r--js/src/frontend/ForOfLoopControl.h98
1 files changed, 98 insertions, 0 deletions
diff --git a/js/src/frontend/ForOfLoopControl.h b/js/src/frontend/ForOfLoopControl.h
new file mode 100644
index 0000000000..dec7737fd6
--- /dev/null
+++ b/js/src/frontend/ForOfLoopControl.h
@@ -0,0 +1,98 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: set ts=8 sts=2 et sw=2 tw=80:
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef frontend_ForOfLoopControl_h
+#define frontend_ForOfLoopControl_h
+
+#include "mozilla/Attributes.h" // MOZ_MUST_USE
+#include "mozilla/Maybe.h" // mozilla::Maybe
+
+#include <stdint.h> // int32_t, uint32_t
+
+#include "jsapi.h" // CompletionKind
+
+#include "frontend/BytecodeControlStructures.h" // NestableControl, LoopControl
+#include "frontend/BytecodeOffset.h" // BytecodeOffset
+#include "frontend/IteratorKind.h" // IteratorKind
+#include "frontend/TryEmitter.h" // TryEmitter
+
+namespace js {
+namespace frontend {
+
+struct BytecodeEmitter;
+class EmitterScope;
+
+class ForOfLoopControl : public LoopControl {
+ // The stack depth of the iterator.
+ int32_t iterDepth_;
+
+ // for-of loops, when throwing from non-iterator code (i.e. from the body
+ // or from evaluating the LHS of the loop condition), need to call
+ // IteratorClose. This is done by enclosing non-iterator code with
+ // try-catch and call IteratorClose in `catch` block.
+ // If IteratorClose itself throws, we must not re-call IteratorClose. Since
+ // non-local jumps like break and return call IteratorClose, whenever a
+ // non-local jump is emitted, we must tell catch block not to perform
+ // IteratorClose.
+ //
+ // for (x of y) {
+ // // Operations for iterator (IteratorNext etc) are outside of
+ // // try-block.
+ // try {
+ // ...
+ // if (...) {
+ // // Before non-local jump, clear iterator on the stack to tell
+ // // catch block not to perform IteratorClose.
+ // tmpIterator = iterator;
+ // iterator = undefined;
+ // IteratorClose(tmpIterator, { break });
+ // break;
+ // }
+ // ...
+ // } catch (e) {
+ // // Just throw again when iterator is cleared by non-local jump.
+ // if (iterator === undefined)
+ // throw e;
+ // IteratorClose(iterator, { throw, e });
+ // }
+ // }
+ mozilla::Maybe<TryEmitter> tryCatch_;
+
+ // Used to track if any yields were emitted between calls to to
+ // emitBeginCodeNeedingIteratorClose and emitEndCodeNeedingIteratorClose.
+ uint32_t numYieldsAtBeginCodeNeedingIterClose_;
+
+ bool allowSelfHosted_;
+
+ IteratorKind iterKind_;
+
+ public:
+ ForOfLoopControl(BytecodeEmitter* bce, int32_t iterDepth,
+ bool allowSelfHosted, IteratorKind iterKind);
+
+ MOZ_MUST_USE bool emitBeginCodeNeedingIteratorClose(BytecodeEmitter* bce);
+ MOZ_MUST_USE bool emitEndCodeNeedingIteratorClose(BytecodeEmitter* bce);
+
+ MOZ_MUST_USE bool emitIteratorCloseInInnermostScopeWithTryNote(
+ BytecodeEmitter* bce,
+ CompletionKind completionKind = CompletionKind::Normal);
+ MOZ_MUST_USE bool emitIteratorCloseInScope(
+ BytecodeEmitter* bce, EmitterScope& currentScope,
+ CompletionKind completionKind = CompletionKind::Normal);
+
+ MOZ_MUST_USE bool emitPrepareForNonLocalJumpFromScope(
+ BytecodeEmitter* bce, EmitterScope& currentScope, bool isTarget,
+ BytecodeOffset* tryNoteStart);
+};
+template <>
+inline bool NestableControl::is<ForOfLoopControl>() const {
+ return kind_ == StatementKind::ForOfLoop;
+}
+
+} /* namespace frontend */
+} /* namespace js */
+
+#endif /* frontend_ForOfLoopControl_h */