Bug 1501666: Make js::AbstractGeneratorObject state checks independent. r=jorendorff
authorJim Blandy <jimb@mozilla.com>
Thu, 25 Apr 2019 16:27:26 +0000
changeset 530488 42558e3db76ee15949c3eacd1182620435fa91d0
parent 530487 09a1e16dfaf1ec52411572132ec73ba444f2288d
child 530489 4c994bf995693ce3daee5adb5097608c8bb800da
push id11265
push userffxbld-merge
push dateMon, 13 May 2019 10:53:39 +0000
treeherdermozilla-beta@77e0fe8dbdd3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1501666: Make js::AbstractGeneratorObject state checks independent. r=jorendorff An AbstractGeneratorObject's RESUME_INDEX_SLOT indicates the state of the generator object: it may be `undefined` (before initial yield), `null` (closed), or an integer (running, closing, or suspended). AbstractGeneratorObject has a number of predicate methods to test for these various states. Unfortunately, some of the predicates grab RESUME_INDEX_SLOT and immediately call `toInt32` on its value, which crashes if it is not an Int32. This means the only safe way to ask if an AbstractGeneratorObject is suspended is: !isBeforeInitialYield() && !isClosed() && isSuspended() If either of the first two conditions is true, isSuspended will assert. This is verbose, and means the predicates cannot be used without studying the details of the RESUME_INDEX_SLOT's representation. This patch makes the predicates assertion-free. isSuspended acquires a new branch, but the others should be just as efficient as they were before. Differential Revision: https://phabricator.services.mozilla.com/D27941
--- a/js/src/vm/GeneratorObject.h
+++ b/js/src/vm/GeneratorObject.h
@@ -123,29 +123,28 @@ class AbstractGeneratorObject : public N
   // JSOP_INITIALYIELD/JSOP_YIELD/JSOP_AWAIT operand) of the yield instruction
   // that suspended the generator. The resumeIndex can be mapped to the
   // bytecode offset (interpreter) or to the native code offset (JIT).
   bool isBeforeInitialYield() const {
     return getFixedSlot(RESUME_INDEX_SLOT).isUndefined();
   bool isRunning() const {
-    MOZ_ASSERT(!isClosed());
-    return getFixedSlot(RESUME_INDEX_SLOT).toInt32() == RESUME_INDEX_RUNNING;
+    return getFixedSlot(RESUME_INDEX_SLOT) == Int32Value(RESUME_INDEX_RUNNING);
   bool isClosing() const {
-    return getFixedSlot(RESUME_INDEX_SLOT).toInt32() == RESUME_INDEX_CLOSING;
+    return getFixedSlot(RESUME_INDEX_SLOT) == Int32Value(RESUME_INDEX_CLOSING);
   bool isSuspended() const {
     // Note: also update Baseline's IsSuspendedGenerator code if this
     // changes.
-    MOZ_ASSERT(!isClosed());
                   "test below should return false for RESUME_INDEX_RUNNING");
-    return getFixedSlot(RESUME_INDEX_SLOT).toInt32() < RESUME_INDEX_CLOSING;
+    Value resumeIndex = getFixedSlot(RESUME_INDEX_SLOT);
+    return resumeIndex.isInt32() && resumeIndex.toInt32() < RESUME_INDEX_CLOSING;
   void setRunning() {
   void setClosing() {