Commit 93d88bf0 authored by Seth Brenith's avatar Seth Brenith Committed by Commit Bot

[torque] Move JSRegExp flags definitions to Torque

This change also removes the kInvalid value from JSRegExp::Flag, so that
the values in JSRegExp::Flag correspond only to those which can exist on
the heap and not things used temporarily during parsing.

Change-Id: I1ded0b1be8c59eab72320edfef26eda42c91a89f
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2216302Reviewed-by: 's avatarSathya Gunasekaran  <gsathya@chromium.org>
Reviewed-by: 's avatarJakob Gruber <jgruber@chromium.org>
Reviewed-by: 's avatarClemens Backes <clemensb@chromium.org>
Reviewed-by: 's avatarTobias Tebbi <tebbi@chromium.org>
Commit-Queue: Seth Brenith <seth.brenith@microsoft.com>
Cr-Commit-Position: refs/heads/master@{#68182}
parent ca54b833
......@@ -557,33 +557,45 @@ class OPTIONAL_DECLSPEC_EMPTY_BASES Optional
return *this;
}
const T* operator->() const {
constexpr const T* operator->() const {
#if V8_HAS_CXX14_CONSTEXPR
DCHECK(storage_.is_populated_);
#endif
return &storage_.value_;
}
T* operator->() {
constexpr T* operator->() {
#if V8_HAS_CXX14_CONSTEXPR
DCHECK(storage_.is_populated_);
#endif
return &storage_.value_;
}
const T& operator*() const & {
constexpr const T& operator*() const& {
#if V8_HAS_CXX14_CONSTEXPR
DCHECK(storage_.is_populated_);
#endif
return storage_.value_;
}
T& operator*() & {
constexpr T& operator*() & {
#if V8_HAS_CXX14_CONSTEXPR
DCHECK(storage_.is_populated_);
#endif
return storage_.value_;
}
const T&& operator*() const && {
constexpr const T&& operator*() const&& {
#if V8_HAS_CXX14_CONSTEXPR
DCHECK(storage_.is_populated_);
#endif
return std::move(storage_.value_);
}
T&& operator*() && {
constexpr T&& operator*() && {
#if V8_HAS_CXX14_CONSTEXPR
DCHECK(storage_.is_populated_);
#endif
return std::move(storage_.value_);
}
......
......@@ -186,8 +186,7 @@ extern enum Flag constexpr 'JSRegExp::Flag' {
kMultiline,
kSticky,
kUnicode,
kDotAll,
kInvalid
kDotAll
}
const kRegExpPrototypeOldFlagGetter: constexpr int31
......
......@@ -6,6 +6,7 @@
#define V8_OBJECTS_JS_REGEXP_H_
#include "src/objects/js-array.h"
#include "torque-generated/bit-fields-tq.h"
// Has to be the last include (doesn't have include guards):
#include "src/objects/object-macros.h"
......@@ -36,40 +37,18 @@ class JSRegExp : public TorqueGeneratedJSRegExp<JSRegExp, JSObject> {
// ATOM: A simple string to match against using an indexOf operation.
// IRREGEXP: Compiled with Irregexp.
enum Type { NOT_COMPILED, ATOM, IRREGEXP };
struct FlagShiftBit {
static constexpr int kGlobal = 0;
static constexpr int kIgnoreCase = 1;
static constexpr int kMultiline = 2;
static constexpr int kSticky = 3;
static constexpr int kUnicode = 4;
static constexpr int kDotAll = 5;
static constexpr int kInvalid = 6;
};
enum Flag : uint8_t {
kNone = 0,
kGlobal = 1 << FlagShiftBit::kGlobal,
kIgnoreCase = 1 << FlagShiftBit::kIgnoreCase,
kMultiline = 1 << FlagShiftBit::kMultiline,
kSticky = 1 << FlagShiftBit::kSticky,
kUnicode = 1 << FlagShiftBit::kUnicode,
kDotAll = 1 << FlagShiftBit::kDotAll,
// Update FlagCount when adding new flags.
kInvalid = 1 << FlagShiftBit::kInvalid, // Not included in FlagCount.
};
using Flags = base::Flags<Flag>;
static constexpr int kFlagCount = 6;
static constexpr Flag FlagFromChar(char c) {
DEFINE_TORQUE_GENERATED_JS_REG_EXP_FLAGS()
static constexpr base::Optional<Flag> FlagFromChar(char c) {
STATIC_ASSERT(kFlagCount == 6);
// clang-format off
return c == 'g' ? kGlobal
: c == 'i' ? kIgnoreCase
: c == 'm' ? kMultiline
: c == 'y' ? kSticky
: c == 'u' ? kUnicode
: c == 's' ? kDotAll
: kInvalid;
return c == 'g' ? base::Optional<Flag>(kGlobal)
: c == 'i' ? base::Optional<Flag>(kIgnoreCase)
: c == 'm' ? base::Optional<Flag>(kMultiline)
: c == 'y' ? base::Optional<Flag>(kSticky)
: c == 'u' ? base::Optional<Flag>(kUnicode)
: c == 's' ? base::Optional<Flag>(kDotAll)
: base::Optional<Flag>();
// clang-format on
}
......
......@@ -2,11 +2,20 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
bitfield struct JSRegExpFlags extends uint31 {
global: bool: 1 bit;
ignore_case: bool: 1 bit;
multiline: bool: 1 bit;
sticky: bool: 1 bit;
unicode: bool: 1 bit;
dot_all: bool: 1 bit;
}
@generateCppClass
extern class JSRegExp extends JSObject {
data: FixedArray|Undefined;
source: String|Undefined;
flags: Smi|Undefined;
flags: SmiTagged<JSRegExpFlags>|Undefined;
}
// Note: Although a condition for a FastJSRegExp is having a positive smi
......
......@@ -6218,12 +6218,12 @@ Handle<Object> JSPromise::TriggerPromiseReactions(Isolate* isolate,
// static
JSRegExp::Flags JSRegExp::FlagsFromString(Isolate* isolate,
Handle<String> flags, bool* success) {
STATIC_ASSERT(JSRegExp::FlagFromChar('g') == JSRegExp::kGlobal);
STATIC_ASSERT(JSRegExp::FlagFromChar('i') == JSRegExp::kIgnoreCase);
STATIC_ASSERT(JSRegExp::FlagFromChar('m') == JSRegExp::kMultiline);
STATIC_ASSERT(JSRegExp::FlagFromChar('s') == JSRegExp::kDotAll);
STATIC_ASSERT(JSRegExp::FlagFromChar('u') == JSRegExp::kUnicode);
STATIC_ASSERT(JSRegExp::FlagFromChar('y') == JSRegExp::kSticky);
STATIC_ASSERT(*JSRegExp::FlagFromChar('g') == JSRegExp::kGlobal);
STATIC_ASSERT(*JSRegExp::FlagFromChar('i') == JSRegExp::kIgnoreCase);
STATIC_ASSERT(*JSRegExp::FlagFromChar('m') == JSRegExp::kMultiline);
STATIC_ASSERT(*JSRegExp::FlagFromChar('s') == JSRegExp::kDotAll);
STATIC_ASSERT(*JSRegExp::FlagFromChar('u') == JSRegExp::kUnicode);
STATIC_ASSERT(*JSRegExp::FlagFromChar('y') == JSRegExp::kSticky);
int length = flags->length();
if (length == 0) {
......@@ -6232,14 +6232,16 @@ JSRegExp::Flags JSRegExp::FlagsFromString(Isolate* isolate,
}
// A longer flags string cannot be valid.
if (length > JSRegExp::kFlagCount) return JSRegExp::Flags(0);
// Initialize {value} to {kInvalid} to allow 2-in-1 duplicate/invalid check.
JSRegExp::Flags value = JSRegExp::kInvalid;
JSRegExp::Flags value(0);
if (flags->IsSeqOneByteString()) {
DisallowHeapAllocation no_gc;
SeqOneByteString seq_flags = SeqOneByteString::cast(*flags);
for (int i = 0; i < length; i++) {
JSRegExp::Flag flag = JSRegExp::FlagFromChar(seq_flags.Get(i));
// Duplicate or invalid flag.
base::Optional<JSRegExp::Flag> maybe_flag =
JSRegExp::FlagFromChar(seq_flags.Get(i));
if (!maybe_flag.has_value()) return JSRegExp::Flags(0);
JSRegExp::Flag flag = *maybe_flag;
// Duplicate flag.
if (value & flag) return JSRegExp::Flags(0);
value |= flag;
}
......@@ -6248,15 +6250,16 @@ JSRegExp::Flags JSRegExp::FlagsFromString(Isolate* isolate,
DisallowHeapAllocation no_gc;
String::FlatContent flags_content = flags->GetFlatContent(no_gc);
for (int i = 0; i < length; i++) {
JSRegExp::Flag flag = JSRegExp::FlagFromChar(flags_content.Get(i));
// Duplicate or invalid flag.
base::Optional<JSRegExp::Flag> maybe_flag =
JSRegExp::FlagFromChar(flags_content.Get(i));
if (!maybe_flag.has_value()) return JSRegExp::Flags(0);
JSRegExp::Flag flag = *maybe_flag;
// Duplicate flag.
if (value & flag) return JSRegExp::Flags(0);
value |= flag;
}
}
*success = true;
// Drop the initially set {kInvalid} bit.
value ^= JSRegExp::kInvalid;
return value;
}
......
......@@ -986,8 +986,9 @@ Maybe<int> Scanner::ScanRegExpFlags() {
// Scan regular expression flags.
JSRegExp::Flags flags;
while (IsIdentifierPart(c0_)) {
JSRegExp::Flags flag = JSRegExp::FlagFromChar(c0_);
if (flag == JSRegExp::kInvalid) return Nothing<int>();
base::Optional<JSRegExp::Flags> maybe_flag = JSRegExp::FlagFromChar(c0_);
if (!maybe_flag.has_value()) return Nothing<int>();
JSRegExp::Flags flag = *maybe_flag;
if (flags & flag) return Nothing<int>();
Advance();
flags |= flag;
......
......@@ -3376,6 +3376,8 @@ void ImplementationVisitor::GenerateBitFields(
}
header << " }; \\\n";
header << " using Flags = base::Flags<Flag>; \\\n";
header << " static constexpr int kFlagCount = "
<< type->fields().size() << "; \\\n";
}
header << "\n";
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment