diff --git a/src/parsing/scanner-character-streams.h b/src/parsing/scanner-character-streams.h
index e6bb3d12e1..2220dee1b9 100644
--- a/src/parsing/scanner-character-streams.h
+++ b/src/parsing/scanner-character-streams.h
@@ -53,16 +53,17 @@ class CharacterStream : public ScannerStream {
   // Returns and advances past the next UTF-16 code unit in the input
   // stream. If there are no more code units it returns kEndOfInput.
   inline uc32 Advance() final {
+    uc32 result = Peek();
+    buffer_cursor_++;
+    return result;
+  }
+
+  inline uc32 Peek() {
     if (V8_LIKELY(buffer_cursor_ < buffer_end_)) {
-      return static_cast<uc32>(*(buffer_cursor_++));
+      return static_cast<uc32>(*buffer_cursor_);
     } else if (ReadBlockChecked()) {
-      return static_cast<uc32>(*(buffer_cursor_++));
+      return static_cast<uc32>(*buffer_cursor_);
     } else {
-      // Note: currently the following increment is necessary to avoid a
-      // parser problem! The scanner treats the final kEndOfInput as
-      // a code unit with a position, and does math relative to that
-      // position.
-      buffer_cursor_++;
       return kEndOfInput;
     }
   }
@@ -105,17 +106,6 @@ class CharacterStream : public ScannerStream {
     }
   }
 
-  // Go back one by two characters in the input stream. (This is the same as
-  // calling Back() twice. But Back() may - in some instances - do substantial
-  // work. Back2() guarantees this work will be done only once.)
-  inline void Back2() {
-    if (V8_LIKELY(buffer_cursor_ - 2 >= buffer_start_)) {
-      buffer_cursor_ -= 2;
-    } else {
-      ReadBlockAt(pos() - 2);
-    }
-  }
-
   inline size_t pos() const final {
     return buffer_pos_ + (buffer_cursor_ - buffer_start_);
   }
@@ -157,7 +147,7 @@ class CharacterStream : public ScannerStream {
   }
 
   void ReadBlockAt(size_t new_pos) {
-    // The callers of this method (Back/Back2/Seek) should handle the easy
+    // The callers of this method (Back/Seek) should handle the easy
     // case (seeking within the current buffer), and we should only get here
     // if we actually require new data.
     // (This is really an efficiency check, not a correctness invariant.)
diff --git a/src/parsing/scanner.cc b/src/parsing/scanner.cc
index f01d4fc398..03476c51bb 100644
--- a/src/parsing/scanner.cc
+++ b/src/parsing/scanner.cc
@@ -415,21 +415,17 @@ Token::Value Scanner::PeekAhead() {
 
 Token::Value Scanner::TryToSkipHTMLCommentAndWhiteSpaces(int start_position) {
   while (true) {
+    DCHECK_EQ('-', c0_);
     Advance();
 
     // If there is an HTML comment end '-->' at the beginning of a
     // line, we treat the rest of the line as a comment. This is in line with
     // the way SpiderMonkey handles it.
-    if (c0_ != '-') {
+    if (c0_ != '-' || Peek() != '>') {
       PushBack('-');  // undo Advance()
       break;
     }
-
     Advance();
-    if (c0_ != '>') {
-      PushBack2('-', '-');  // undo 2x Advance();
-      break;
-    }
 
     // Treat the rest of the line as a comment.
     Token::Value token = SkipSingleHTMLComment();
@@ -566,16 +562,11 @@ Token::Value Scanner::ScanHtmlComment() {
   // Check for <!-- comments.
   DCHECK_EQ(c0_, '!');
   Advance();
-  if (c0_ != '-') {
+  if (c0_ != '-' || Peek() != '-') {
     PushBack('!');  // undo Advance()
     return Token::LT;
   }
-
   Advance();
-  if (c0_ != '-') {
-    PushBack2('-', '!');  // undo 2x Advance()
-    return Token::LT;
-  }
 
   found_html_comment_ = true;
   return SkipSingleHTMLComment();
diff --git a/src/parsing/scanner.h b/src/parsing/scanner.h
index 158e735290..a28206edcf 100644
--- a/src/parsing/scanner.h
+++ b/src/parsing/scanner.h
@@ -500,22 +500,12 @@ class Scanner {
   }
 
   void PushBack(uc32 ch) {
-    if (c0_ > static_cast<uc32>(unibrow::Utf16::kMaxNonSurrogateCharCode)) {
-      source_->Back2();
-    } else {
-      source_->Back();
-    }
+    DCHECK_LE(c0_, static_cast<uc32>(unibrow::Utf16::kMaxNonSurrogateCharCode));
+    source_->Back();
     c0_ = ch;
   }
 
-  // Same as PushBack(ch1); PushBack(ch2).
-  // - Potentially more efficient as it uses Back2() on the stream.
-  // - Uses char as parameters, since we're only calling it with ASCII chars in
-  //   practice. This way, we can avoid a few edge cases.
-  void PushBack2(char ch1, char ch2) {
-    source_->Back2();
-    c0_ = ch2;
-  }
+  uc32 Peek() const { return source_->Peek(); }
 
   inline Token::Value Select(Token::Value tok) {
     Advance();