Bug 1473796 - Part 1: Add DefaultEmitter. r=jorendorff
authorTooru Fujisawa <arai_a@mac.com>
Tue, 12 Mar 2019 06:03:30 +0000
changeset 521488 f53c8cedef75
parent 521487 89679dcecb8a
child 521489 d20d700c80d5
push id10866
push usernerli@mozilla.com
push dateTue, 12 Mar 2019 18:59:09 +0000
treeherdermozilla-beta@445c24a51727 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjorendorff
bugs1473796
milestone67.0a1
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 1473796 - Part 1: Add DefaultEmitter. r=jorendorff Differential Revision: https://phabricator.services.mozilla.com/D19619
js/src/frontend/BytecodeEmitter.cpp
js/src/frontend/DefaultEmitter.cpp
js/src/frontend/DefaultEmitter.h
js/src/frontend/moz.build
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -24,16 +24,17 @@
 #include "jsnum.h"
 #include "jstypes.h"
 #include "jsutil.h"
 
 #include "ds/Nestable.h"
 #include "frontend/BytecodeControlStructures.h"
 #include "frontend/CallOrNewEmitter.h"
 #include "frontend/CForEmitter.h"
+#include "frontend/DefaultEmitter.h"  // DefaultEmitter
 #include "frontend/DoWhileEmitter.h"
 #include "frontend/ElemOpEmitter.h"
 #include "frontend/EmitterScope.h"
 #include "frontend/ExpressionStatementEmitter.h"
 #include "frontend/ForInEmitter.h"
 #include "frontend/ForOfEmitter.h"
 #include "frontend/ForOfLoopControl.h"
 #include "frontend/IfEmitter.h"
@@ -3136,49 +3137,28 @@ bool BytecodeEmitter::wrapWithDestructur
   ptrdiff_t end = offset();
   if (start != end) {
     return addTryNote(JSTRY_DESTRUCTURING, iterDepth, start, end);
   }
   return true;
 }
 
 bool BytecodeEmitter::emitDefault(ParseNode* defaultExpr, ParseNode* pattern) {
-  IfEmitter ifUndefined(this);
-  if (!ifUndefined.emitIf(Nothing())) {
-    return false;
-  }
-
-  if (!emit1(JSOP_DUP)) {
-    //              [stack] VALUE VALUE
-    return false;
-  }
-  if (!emit1(JSOP_UNDEFINED)) {
-    //              [stack] VALUE VALUE UNDEFINED
-    return false;
-  }
-  if (!emit1(JSOP_STRICTEQ)) {
-    //              [stack] VALUE EQ?
-    return false;
-  }
-
-  if (!ifUndefined.emitThen()) {
-    //              [stack] VALUE
-    return false;
-  }
-
-  if (!emit1(JSOP_POP)) {
+  //                [stack] VALUE
+
+  DefaultEmitter de(this);
+  if (!de.prepareForDefault()) {
     //              [stack]
     return false;
   }
   if (!emitInitializer(defaultExpr, pattern)) {
     //              [stack] DEFAULTVALUE
     return false;
   }
-
-  if (!ifUndefined.emitEnd()) {
+  if (!de.emitEnd()) {
     //              [stack] VALUE/DEFAULTVALUE
     return false;
   }
   return true;
 }
 
 bool BytecodeEmitter::emitAnonymousFunctionWithName(ParseNode* node,
                                                     HandleAtom name) {
new file mode 100644
--- /dev/null
+++ b/js/src/frontend/DefaultEmitter.cpp
@@ -0,0 +1,76 @@
+/* -*- 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/. */
+
+#include "frontend/DefaultEmitter.h"
+
+#include "mozilla/Assertions.h"  // MOZ_ASSERT
+
+#include "frontend/BytecodeEmitter.h"  // BytecodeEmitter
+#include "vm/Opcodes.h"                // JSOP_*
+
+using namespace js;
+using namespace js::frontend;
+
+using mozilla::Maybe;
+using mozilla::Nothing;
+
+DefaultEmitter::DefaultEmitter(BytecodeEmitter* bce) : bce_(bce) {}
+
+bool DefaultEmitter::prepareForDefault() {
+  MOZ_ASSERT(state_ == State::Start);
+
+  //                [stack] VALUE
+
+  ifUndefined_.emplace(bce_);
+  if (!ifUndefined_->emitIf(Nothing())) {
+    return false;
+  }
+
+  if (!bce_->emit1(JSOP_DUP)) {
+    //              [stack] VALUE VALUE
+    return false;
+  }
+  if (!bce_->emit1(JSOP_UNDEFINED)) {
+    //              [stack] VALUE VALUE UNDEFINED
+    return false;
+  }
+  if (!bce_->emit1(JSOP_STRICTEQ)) {
+    //              [stack] VALUE EQ?
+    return false;
+  }
+
+  if (!ifUndefined_->emitThen()) {
+    //              [stack] VALUE
+    return false;
+  }
+
+  if (!bce_->emit1(JSOP_POP)) {
+    //              [stack]
+    return false;
+  }
+
+#ifdef DEBUG
+  state_ = State::Default;
+#endif
+  return true;
+}
+
+bool DefaultEmitter::emitEnd() {
+  MOZ_ASSERT(state_ == State::Default);
+
+  //                [stack] DEFAULTVALUE
+
+  if (!ifUndefined_->emitEnd()) {
+    //              [stack] VALUE/DEFAULTVALUE
+    return false;
+  }
+  ifUndefined_.reset();
+
+#ifdef DEBUG
+  state_ = State::End;
+#endif
+  return true;
+}
new file mode 100644
--- /dev/null
+++ b/js/src/frontend/DefaultEmitter.h
@@ -0,0 +1,65 @@
+/* -*- 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_DefaultEmitter_h
+#define frontend_DefaultEmitter_h
+
+#include "mozilla/Attributes.h"  // MOZ_STACK_CLASS, MOZ_MUST_USE
+#include "mozilla/Maybe.h"       // Maybe
+
+#include "frontend/IfEmitter.h"  // IfEmitter
+
+namespace js {
+namespace frontend {
+
+struct BytecodeEmitter;
+
+// Class for emitting default parameter or default value.
+//
+// Usage: (check for the return value is omitted for simplicity)
+//
+//   `x = 10` in `function (x = 10) {}`
+//     // the value of arguments[0] is on the stack
+//     DefaultEmitter de(this);
+//     de.prepareForDefault();
+//     emit(10);
+//     de.emitEnd();
+//
+class MOZ_STACK_CLASS DefaultEmitter {
+  BytecodeEmitter* bce_;
+
+  mozilla::Maybe<IfEmitter> ifUndefined_;
+
+#ifdef DEBUG
+  // The state of this emitter.
+  //
+  // +-------+ prepareForDefault +---------+ emitEnd +-----+
+  // | Start |------------------>| Default |-------->| End |
+  // +-------+                   +---------+         +-----+
+  enum class State {
+    // The initial state.
+    Start,
+
+    // After calling prepareForDefault.
+    Default,
+
+    // After calling emitEnd.
+    End
+  };
+  State state_ = State::Start;
+#endif
+
+ public:
+  explicit DefaultEmitter(BytecodeEmitter* bce);
+
+  MOZ_MUST_USE bool prepareForDefault();
+  MOZ_MUST_USE bool emitEnd();
+};
+
+} /* namespace frontend */
+} /* namespace js */
+
+#endif /* frontend_LabelEmitter_h */
--- a/js/src/frontend/moz.build
+++ b/js/src/frontend/moz.build
@@ -24,16 +24,17 @@ ReservedWordsGenerated.inputs += ['Reser
 
 
 UNIFIED_SOURCES += [
     'BytecodeCompiler.cpp',
     'BytecodeControlStructures.cpp',
     'BytecodeEmitter.cpp',
     'CallOrNewEmitter.cpp',
     'CForEmitter.cpp',
+    'DefaultEmitter.cpp',
     'DoWhileEmitter.cpp',
     'ElemOpEmitter.cpp',
     'EmitterScope.cpp',
     'ExpressionStatementEmitter.cpp',
     'FoldConstants.cpp',
     'ForInEmitter.cpp',
     'ForOfEmitter.cpp',
     'ForOfLoopControl.cpp',