Revert "[regexp] Implement the match indices proposal"
This reverts commit 9460101cdb
.
Reason for revert: Causes confusion on Blink side, as it introduces
an object with >=2 internal fields that is not a wrapper (see bug).
Bug: chromium:996681
Change-Id: I275b5a064a4ee8c73c05f97be322924a3bc5370e
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1769148
Reviewed-by: Adam Klein <adamk@chromium.org>
Commit-Queue: Joshua Litt <joshualitt@chromium.org>
Cr-Commit-Position: refs/heads/master@{#63386}
This commit is contained in:
parent
7fd1922823
commit
1fcbe01a04
2
BUILD.gn
2
BUILD.gn
@ -913,7 +913,6 @@ action("postmortem-metadata") {
|
||||
"src/objects/js-promise-inl.h",
|
||||
"src/objects/js-promise.h",
|
||||
"src/objects/js-regexp-inl.h",
|
||||
"src/objects/js-regexp.cc",
|
||||
"src/objects/js-regexp.h",
|
||||
"src/objects/js-regexp-string-iterator-inl.h",
|
||||
"src/objects/js-regexp-string-iterator.h",
|
||||
@ -2554,7 +2553,6 @@ v8_source_set("v8_base_without_compiler") {
|
||||
"src/objects/js-regexp-inl.h",
|
||||
"src/objects/js-regexp-string-iterator-inl.h",
|
||||
"src/objects/js-regexp-string-iterator.h",
|
||||
"src/objects/js-regexp.cc",
|
||||
"src/objects/js-regexp.h",
|
||||
"src/objects/js-relative-time-format-inl.h",
|
||||
"src/objects/js-relative-time-format.cc",
|
||||
|
@ -16,7 +16,6 @@
|
||||
#include "src/objects/contexts.h"
|
||||
#include "src/objects/field-index-inl.h"
|
||||
#include "src/objects/js-array-inl.h"
|
||||
#include "src/objects/js-regexp-inl.h"
|
||||
#include "src/objects/module-inl.h"
|
||||
#include "src/objects/property-details.h"
|
||||
#include "src/objects/prototype.h"
|
||||
@ -841,25 +840,5 @@ Handle<AccessorInfo> Accessors::MakeErrorStackInfo(Isolate* isolate) {
|
||||
&ErrorStackGetter, &ErrorStackSetter);
|
||||
}
|
||||
|
||||
//
|
||||
// Accessors::RegExpResultIndices
|
||||
//
|
||||
|
||||
void Accessors::RegExpResultIndicesGetter(
|
||||
v8::Local<v8::Name> key, const v8::PropertyCallbackInfo<v8::Value>& info) {
|
||||
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
|
||||
HandleScope scope(isolate);
|
||||
Handle<JSRegExpResult> regexp_result(
|
||||
Handle<JSRegExpResult>::cast(Utils::OpenHandle(*info.Holder())));
|
||||
Handle<Object> indices(
|
||||
JSRegExpResult::GetAndCacheIndices(isolate, regexp_result));
|
||||
info.GetReturnValue().Set(Utils::ToLocal(indices));
|
||||
}
|
||||
|
||||
Handle<AccessorInfo> Accessors::MakeRegExpResultIndicesInfo(Isolate* isolate) {
|
||||
return MakeAccessor(isolate, isolate->factory()->indices_string(),
|
||||
&RegExpResultIndicesGetter, nullptr);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
@ -43,8 +43,6 @@ class JavaScriptFrame;
|
||||
kHasSideEffectToReceiver) \
|
||||
V(_, function_prototype, FunctionPrototype, kHasNoSideEffect, \
|
||||
kHasSideEffectToReceiver) \
|
||||
V(_, regexp_result_indices, RegExpResultIndices, kHasSideEffectToReceiver, \
|
||||
kHasSideEffectToReceiver) \
|
||||
V(_, string_length, StringLength, kHasNoSideEffect, kHasSideEffectToReceiver)
|
||||
|
||||
#define ACCESSOR_SETTER_LIST(V) \
|
||||
|
@ -1284,22 +1284,11 @@ RegExpBuiltinsAssembler::FastStoreLastIndex(FastJSRegExp, Smi): void;
|
||||
|
||||
@hasSameInstanceTypeAsParent
|
||||
extern class JSRegExpResult extends JSArray {
|
||||
// The below fields are for internal use only.
|
||||
cached_indices_or_match_info: JSRegExpResultIndices | RegExpMatchInfo;
|
||||
names: FixedArray | Undefined;
|
||||
|
||||
// The below fields are externally exposed.
|
||||
index: Object;
|
||||
input: Object;
|
||||
groups: Object;
|
||||
}
|
||||
|
||||
@hasSameInstanceTypeAsParent
|
||||
extern class JSRegExpResultIndices extends JSArray {
|
||||
// The groups field is externally exposed.
|
||||
groups: Object;
|
||||
}
|
||||
|
||||
extern class JSRegExpStringIterator extends JSObject {
|
||||
iterating_reg_exp: Object;
|
||||
iterated_string: String;
|
||||
|
@ -35,8 +35,7 @@ TNode<IntPtrT> RegExpBuiltinsAssembler::IntPtrZero() {
|
||||
|
||||
TNode<JSRegExpResult> RegExpBuiltinsAssembler::AllocateRegExpResult(
|
||||
TNode<Context> context, TNode<Smi> length, TNode<Smi> index,
|
||||
TNode<String> input, TNode<RegExpMatchInfo> match_info,
|
||||
TNode<FixedArray>* elements_out) {
|
||||
TNode<String> input, TNode<FixedArray>* elements_out) {
|
||||
CSA_ASSERT(this, SmiLessThanOrEqual(
|
||||
length, SmiConstant(JSArray::kMaxFastArrayLength)));
|
||||
CSA_ASSERT(this, SmiGreaterThan(length, SmiConstant(0)));
|
||||
@ -63,22 +62,11 @@ TNode<JSRegExpResult> RegExpBuiltinsAssembler::AllocateRegExpResult(
|
||||
|
||||
TNode<JSRegExpResult> result = CAST(array);
|
||||
|
||||
// Load undefined value once here to avoid multiple LoadRoots.
|
||||
TNode<Oddball> undefined_value =
|
||||
UncheckedCast<Oddball>(LoadRoot(RootIndex::kUndefinedValue));
|
||||
|
||||
StoreObjectFieldNoWriteBarrier(result, JSRegExpResult::kIndexOffset, index);
|
||||
// TODO(jgruber,tebbi): Could skip barrier but the MemoryOptimizer complains.
|
||||
StoreObjectField(result, JSRegExpResult::kInputOffset, input);
|
||||
StoreObjectFieldNoWriteBarrier(result, JSRegExpResult::kGroupsOffset,
|
||||
undefined_value);
|
||||
StoreObjectFieldNoWriteBarrier(result, JSRegExpResult::kNamesOffset,
|
||||
undefined_value);
|
||||
|
||||
// Stash match_info in order to build JSRegExpResultIndices lazily when the
|
||||
// 'indices' property is accessed.
|
||||
StoreObjectField(result, JSRegExpResult::kCachedIndicesOrMatchInfoOffset,
|
||||
match_info);
|
||||
UndefinedConstant());
|
||||
|
||||
// Finish elements initialization.
|
||||
|
||||
@ -180,7 +168,7 @@ TNode<JSRegExpResult> RegExpBuiltinsAssembler::ConstructNewResultFromMatchInfo(
|
||||
|
||||
TNode<FixedArray> result_elements;
|
||||
TNode<JSRegExpResult> result = AllocateRegExpResult(
|
||||
context, num_results, start, string, match_info, &result_elements);
|
||||
context, num_results, start, string, &result_elements);
|
||||
|
||||
UnsafeStoreFixedArrayElement(result_elements, 0, first);
|
||||
|
||||
@ -256,9 +244,6 @@ TNode<JSRegExpResult> RegExpBuiltinsAssembler::ConstructNewResultFromMatchInfo(
|
||||
TNode<IntPtrT> names_length = LoadAndUntagFixedArrayBaseLength(names);
|
||||
CSA_ASSERT(this, IntPtrGreaterThan(names_length, IntPtrZero()));
|
||||
|
||||
// Stash names in case we need them to build the indices array later.
|
||||
StoreObjectField(result, JSRegExpResult::kNamesOffset, names);
|
||||
|
||||
// Allocate a new object to store the named capture properties.
|
||||
// TODO(jgruber): Could be optimized by adding the object map to the heap
|
||||
// root list.
|
||||
|
@ -35,8 +35,7 @@ class RegExpBuiltinsAssembler : public CodeStubAssembler {
|
||||
// and input string.
|
||||
TNode<JSRegExpResult> AllocateRegExpResult(
|
||||
TNode<Context> context, TNode<Smi> length, TNode<Smi> index,
|
||||
TNode<String> input, TNode<RegExpMatchInfo> match_info,
|
||||
TNode<FixedArray>* elements_out = nullptr);
|
||||
TNode<String> input, TNode<FixedArray>* elements_out = nullptr);
|
||||
|
||||
TNode<Object> FastLoadLastIndexBeforeSmiCheck(TNode<JSRegExp> regexp);
|
||||
TNode<Smi> FastLoadLastIndex(TNode<JSRegExp> regexp) {
|
||||
|
@ -208,7 +208,6 @@ DEFINE_IMPLICATION(harmony_import_meta, harmony_dynamic_import)
|
||||
V(harmony_regexp_sequence, "RegExp Unicode sequence properties") \
|
||||
V(harmony_weak_refs, "harmony weak references") \
|
||||
V(harmony_optional_chaining, "harmony optional chaining syntax") \
|
||||
V(harmony_regexp_match_indices, "harmony regexp match indices") \
|
||||
V(harmony_nullish, "harmony nullish operator")
|
||||
|
||||
#ifdef V8_INTL_SUPPORT
|
||||
|
@ -284,10 +284,6 @@ class Genesis {
|
||||
void TransferNamedProperties(Handle<JSObject> from, Handle<JSObject> to);
|
||||
void TransferIndexedProperties(Handle<JSObject> from, Handle<JSObject> to);
|
||||
|
||||
Handle<Map> CreateInitialMapForArraySubclass(int size,
|
||||
int inobject_properties,
|
||||
int additional_properties = 0);
|
||||
|
||||
static bool CompileExtension(Isolate* isolate, v8::Extension* extension);
|
||||
|
||||
Isolate* isolate_;
|
||||
@ -4423,17 +4419,6 @@ void Genesis::InitializeGlobal_harmony_promise_all_settled() {
|
||||
}
|
||||
}
|
||||
|
||||
void Genesis::InitializeGlobal_harmony_regexp_match_indices() {
|
||||
if (!FLAG_harmony_regexp_match_indices) return;
|
||||
|
||||
// Add indices accessor to JSRegExpResult's initial map.
|
||||
Handle<Map> initial_map(native_context()->regexp_result_map(), isolate());
|
||||
Descriptor d = Descriptor::AccessorConstant(
|
||||
factory()->indices_string(), factory()->regexp_result_indices_accessor(),
|
||||
NONE);
|
||||
initial_map->AppendDescriptor(isolate(), &d);
|
||||
}
|
||||
|
||||
#ifdef V8_INTL_SUPPORT
|
||||
|
||||
void Genesis::InitializeGlobal_harmony_intl_date_format_range() {
|
||||
@ -4915,12 +4900,42 @@ bool Genesis::InstallNatives() {
|
||||
// predefines the properties index, input, and groups).
|
||||
{
|
||||
// JSRegExpResult initial map.
|
||||
// Add additional slack to the initial map in case regexp_match_indices
|
||||
// are enabled to account for the additional descriptor.
|
||||
int additional_slack = 1;
|
||||
Handle<Map> initial_map = CreateInitialMapForArraySubclass(
|
||||
JSRegExpResult::kSize, JSRegExpResult::kInObjectPropertyCount,
|
||||
additional_slack);
|
||||
|
||||
// Find global.Array.prototype to inherit from.
|
||||
Handle<JSFunction> array_constructor(native_context()->array_function(),
|
||||
isolate());
|
||||
Handle<JSObject> array_prototype(
|
||||
JSObject::cast(array_constructor->instance_prototype()), isolate());
|
||||
|
||||
// Add initial map.
|
||||
Handle<Map> initial_map = factory()->NewMap(
|
||||
JS_ARRAY_TYPE, JSRegExpResult::kSize, TERMINAL_FAST_ELEMENTS_KIND,
|
||||
JSRegExpResult::kInObjectPropertyCount);
|
||||
initial_map->SetConstructor(*array_constructor);
|
||||
|
||||
// Set prototype on map.
|
||||
initial_map->set_has_non_instance_prototype(false);
|
||||
Map::SetPrototype(isolate(), initial_map, array_prototype);
|
||||
|
||||
// Update map with length accessor from Array and add "index", "input" and
|
||||
// "groups".
|
||||
Map::EnsureDescriptorSlack(isolate(), initial_map,
|
||||
JSRegExpResult::kInObjectPropertyCount + 1);
|
||||
|
||||
// length descriptor.
|
||||
{
|
||||
JSFunction array_function = native_context()->array_function();
|
||||
Handle<DescriptorArray> array_descriptors(
|
||||
array_function.initial_map().instance_descriptors(), isolate());
|
||||
Handle<String> length = factory()->length_string();
|
||||
int old = array_descriptors->SearchWithCache(
|
||||
isolate(), *length, array_function.initial_map());
|
||||
DCHECK_NE(old, DescriptorArray::kNotFound);
|
||||
Descriptor d = Descriptor::AccessorConstant(
|
||||
length, handle(array_descriptors->GetStrongValue(old), isolate()),
|
||||
array_descriptors->GetDetails(old).attributes());
|
||||
initial_map->AppendDescriptor(isolate(), &d);
|
||||
}
|
||||
|
||||
// index descriptor.
|
||||
{
|
||||
@ -4949,27 +4964,6 @@ bool Genesis::InstallNatives() {
|
||||
native_context()->set_regexp_result_map(*initial_map);
|
||||
}
|
||||
|
||||
// Create a constructor for JSRegExpResultIndices (a variant of Array that
|
||||
// predefines the groups property).
|
||||
{
|
||||
// JSRegExpResultIndices initial map.
|
||||
Handle<Map> initial_map = CreateInitialMapForArraySubclass(
|
||||
JSRegExpResultIndices::kSize,
|
||||
JSRegExpResultIndices::kInObjectPropertyCount);
|
||||
|
||||
// groups descriptor.
|
||||
{
|
||||
Descriptor d = Descriptor::DataField(
|
||||
isolate(), factory()->groups_string(),
|
||||
JSRegExpResultIndices::kGroupsIndex, NONE, Representation::Tagged());
|
||||
initial_map->AppendDescriptor(isolate(), &d);
|
||||
DCHECK_EQ(initial_map->LastAdded(),
|
||||
JSRegExpResultIndices::kGroupsDescriptorIndex);
|
||||
}
|
||||
|
||||
native_context()->set_regexp_result_indices_map(*initial_map);
|
||||
}
|
||||
|
||||
// Add @@iterator method to the arguments object maps.
|
||||
{
|
||||
PropertyAttributes attribs = DONT_ENUM;
|
||||
@ -5371,47 +5365,6 @@ void Genesis::TransferObject(Handle<JSObject> from, Handle<JSObject> to) {
|
||||
JSObject::ForceSetPrototype(to, proto);
|
||||
}
|
||||
|
||||
Handle<Map> Genesis::CreateInitialMapForArraySubclass(int size,
|
||||
int inobject_properties,
|
||||
int additional_slack) {
|
||||
// Find global.Array.prototype to inherit from.
|
||||
Handle<JSFunction> array_constructor(native_context()->array_function(),
|
||||
isolate());
|
||||
Handle<JSObject> array_prototype(native_context()->initial_array_prototype(),
|
||||
isolate());
|
||||
|
||||
// Add initial map.
|
||||
Handle<Map> initial_map = factory()->NewMap(
|
||||
JS_ARRAY_TYPE, size, TERMINAL_FAST_ELEMENTS_KIND, inobject_properties);
|
||||
initial_map->SetConstructor(*array_constructor);
|
||||
|
||||
// Set prototype on map.
|
||||
initial_map->set_has_non_instance_prototype(false);
|
||||
Map::SetPrototype(isolate(), initial_map, array_prototype);
|
||||
|
||||
// Update map with length accessor from Array.
|
||||
static constexpr int kTheLengthAccessor = 1;
|
||||
Map::EnsureDescriptorSlack(
|
||||
isolate(), initial_map,
|
||||
inobject_properties + kTheLengthAccessor + additional_slack);
|
||||
|
||||
// length descriptor.
|
||||
{
|
||||
JSFunction array_function = native_context()->array_function();
|
||||
Handle<DescriptorArray> array_descriptors(
|
||||
array_function.initial_map().instance_descriptors(), isolate());
|
||||
Handle<String> length = factory()->length_string();
|
||||
int old = array_descriptors->SearchWithCache(isolate(), *length,
|
||||
array_function.initial_map());
|
||||
DCHECK_NE(old, DescriptorArray::kNotFound);
|
||||
Descriptor d = Descriptor::AccessorConstant(
|
||||
length, handle(array_descriptors->GetStrongValue(old), isolate()),
|
||||
array_descriptors->GetDetails(old).attributes());
|
||||
initial_map->AppendDescriptor(isolate(), &d);
|
||||
}
|
||||
return initial_map;
|
||||
}
|
||||
|
||||
Genesis::Genesis(
|
||||
Isolate* isolate, MaybeHandle<JSGlobalProxy> maybe_global_proxy,
|
||||
v8::Local<v8::ObjectTemplate> global_proxy_template,
|
||||
|
@ -202,7 +202,6 @@
|
||||
V(_, illegal_access_string, "illegal access") \
|
||||
V(_, illegal_argument_string, "illegal argument") \
|
||||
V(_, index_string, "index") \
|
||||
V(_, indices_string, "indices") \
|
||||
V(_, Infinity_string, "Infinity") \
|
||||
V(_, infinity_string, "infinity") \
|
||||
V(_, input_string, "input") \
|
||||
|
@ -233,7 +233,6 @@ enum ContextLookupFlags {
|
||||
V(REGEXP_PROTOTYPE_MAP_INDEX, Map, regexp_prototype_map) \
|
||||
V(REGEXP_REPLACE_FUNCTION_INDEX, JSFunction, regexp_replace_function) \
|
||||
V(REGEXP_RESULT_MAP_INDEX, Map, regexp_result_map) \
|
||||
V(REGEXP_RESULT_INDICES_MAP_INDEX, Map, regexp_result_indices_map) \
|
||||
V(REGEXP_SEARCH_FUNCTION_INDEX, JSFunction, regexp_search_function) \
|
||||
V(REGEXP_SPECIES_PROTECTOR_INDEX, PropertyCell, regexp_species_protector) \
|
||||
V(REGEXP_SPLIT_FUNCTION_INDEX, JSFunction, regexp_split_function) \
|
||||
|
@ -451,7 +451,6 @@ V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
|
||||
V(JSProxy, JS_PROXY_TYPE) \
|
||||
V(JSRegExp, JS_REGEXP_TYPE) \
|
||||
V(JSRegExpResult, JS_ARRAY_TYPE) \
|
||||
V(JSRegExpResultIndices, JS_ARRAY_TYPE) \
|
||||
V(JSRegExpStringIterator, JS_REGEXP_STRING_ITERATOR_TYPE) \
|
||||
V(JSSet, JS_SET_TYPE) \
|
||||
V(JSStringIterator, JS_STRING_ITERATOR_TYPE) \
|
||||
|
@ -7,7 +7,6 @@
|
||||
|
||||
#include "src/objects/js-regexp.h"
|
||||
|
||||
#include "src/objects/js-array-inl.h"
|
||||
#include "src/objects/objects-inl.h" // Needed for write barriers
|
||||
#include "src/objects/smi.h"
|
||||
#include "src/objects/string.h"
|
||||
@ -19,22 +18,14 @@ namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
OBJECT_CONSTRUCTORS_IMPL(JSRegExp, JSObject)
|
||||
OBJECT_CONSTRUCTORS_IMPL(JSRegExpResult, JSArray)
|
||||
OBJECT_CONSTRUCTORS_IMPL(JSRegExpResultIndices, JSArray)
|
||||
|
||||
CAST_ACCESSOR(JSRegExp)
|
||||
CAST_ACCESSOR(JSRegExpResult)
|
||||
CAST_ACCESSOR(JSRegExpResultIndices)
|
||||
|
||||
ACCESSORS(JSRegExp, data, Object, kDataOffset)
|
||||
ACCESSORS(JSRegExp, flags, Object, kFlagsOffset)
|
||||
ACCESSORS(JSRegExp, source, Object, kSourceOffset)
|
||||
ACCESSORS(JSRegExp, last_index, Object, kLastIndexOffset)
|
||||
|
||||
ACCESSORS(JSRegExpResult, cached_indices_or_match_info, Object,
|
||||
kCachedIndicesOrMatchInfoOffset)
|
||||
ACCESSORS(JSRegExpResult, names, Object, kNamesOffset)
|
||||
|
||||
JSRegExp::Type JSRegExp::TypeTag() const {
|
||||
Object data = this->data();
|
||||
if (data.IsUndefined()) return JSRegExp::NOT_COMPILED;
|
||||
|
@ -1,118 +0,0 @@
|
||||
// Copyright 2019 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "src/objects/js-regexp.h"
|
||||
|
||||
#include "src/objects/js-array-inl.h"
|
||||
#include "src/objects/js-regexp-inl.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
Handle<JSArray> JSRegExpResult::GetAndCacheIndices(
|
||||
Isolate* isolate, Handle<JSRegExpResult> regexp_result) {
|
||||
// Check for cached indices.
|
||||
Handle<Object> indices_or_match_info(
|
||||
regexp_result->cached_indices_or_match_info(), isolate);
|
||||
if (indices_or_match_info->IsRegExpMatchInfo()) {
|
||||
// Build and cache indices for next lookup.
|
||||
// TODO(joshualitt): Instead of caching the indices, we could call
|
||||
// ReconfigureToDataProperty on 'indices' setting its value to this
|
||||
// newly created array. However, care would have to be taken to ensure
|
||||
// a new map is not created each time.
|
||||
Handle<RegExpMatchInfo> match_info(
|
||||
RegExpMatchInfo::cast(regexp_result->cached_indices_or_match_info()),
|
||||
isolate);
|
||||
Handle<Object> maybe_names(regexp_result->names(), isolate);
|
||||
indices_or_match_info =
|
||||
JSRegExpResultIndices::BuildIndices(isolate, match_info, maybe_names);
|
||||
|
||||
// Cache the result and clear the names array.
|
||||
regexp_result->set_cached_indices_or_match_info(*indices_or_match_info);
|
||||
regexp_result->set_names(ReadOnlyRoots(isolate).undefined_value());
|
||||
}
|
||||
return Handle<JSArray>::cast(indices_or_match_info);
|
||||
}
|
||||
|
||||
Handle<JSRegExpResultIndices> JSRegExpResultIndices::BuildIndices(
|
||||
Isolate* isolate, Handle<RegExpMatchInfo> match_info,
|
||||
Handle<Object> maybe_names) {
|
||||
Handle<JSRegExpResultIndices> indices(Handle<JSRegExpResultIndices>::cast(
|
||||
isolate->factory()->NewJSObjectFromMap(
|
||||
isolate->regexp_result_indices_map())));
|
||||
|
||||
// Initialize indices length to avoid having a partially initialized object
|
||||
// should GC be triggered by creating a NewFixedArray.
|
||||
indices->set_length(Smi::kZero);
|
||||
|
||||
// Build indices array from RegExpMatchInfo.
|
||||
int num_indices = match_info->NumberOfCaptureRegisters();
|
||||
int num_results = num_indices >> 1;
|
||||
Handle<FixedArray> indices_array =
|
||||
isolate->factory()->NewFixedArray(num_results);
|
||||
JSArray::SetContent(indices, indices_array);
|
||||
|
||||
for (int i = 0; i < num_results; i++) {
|
||||
int base_offset = i * 2;
|
||||
int start_offset = match_info->Capture(base_offset);
|
||||
int end_offset = match_info->Capture(base_offset + 1);
|
||||
|
||||
// Any unmatched captures are set to undefined, otherwise we set them to a
|
||||
// subarray of the indices.
|
||||
if (start_offset == -1) {
|
||||
indices_array->set(i, ReadOnlyRoots(isolate).undefined_value());
|
||||
} else {
|
||||
Handle<FixedArray> indices_sub_array(
|
||||
isolate->factory()->NewFixedArray(2));
|
||||
indices_sub_array->set(0, Smi::FromInt(start_offset));
|
||||
indices_sub_array->set(1, Smi::FromInt(end_offset));
|
||||
Handle<JSArray> indices_sub_jsarray =
|
||||
isolate->factory()->NewJSArrayWithElements(indices_sub_array,
|
||||
PACKED_SMI_ELEMENTS, 2);
|
||||
indices_array->set(i, *indices_sub_jsarray);
|
||||
}
|
||||
}
|
||||
|
||||
// If there are no capture groups, set the groups property to undefined.
|
||||
FieldIndex groups_index =
|
||||
FieldIndex::ForDescriptor(indices->map(), kGroupsDescriptorIndex);
|
||||
if (maybe_names->IsUndefined(isolate)) {
|
||||
indices->RawFastPropertyAtPut(groups_index,
|
||||
ReadOnlyRoots(isolate).undefined_value());
|
||||
return indices;
|
||||
}
|
||||
|
||||
// Create a groups property which returns a dictionary of named captures to
|
||||
// their corresponding capture indices.
|
||||
Handle<FixedArray> names(Handle<FixedArray>::cast(maybe_names));
|
||||
int num_names = names->length() >> 1;
|
||||
Handle<NameDictionary> group_names = NameDictionary::New(isolate, num_names);
|
||||
for (int i = 0; i < num_names; i++) {
|
||||
int base_offset = i * 2;
|
||||
int name_offset = base_offset;
|
||||
int index_offset = base_offset + 1;
|
||||
Handle<String> name(String::cast(names->get(name_offset)), isolate);
|
||||
Handle<Smi> smi_index(Smi::cast(names->get(index_offset)), isolate);
|
||||
Handle<Object> capture_indices(indices_array->get(smi_index->value()),
|
||||
isolate);
|
||||
if (!capture_indices->IsUndefined(isolate)) {
|
||||
capture_indices = Handle<JSArray>::cast(capture_indices);
|
||||
}
|
||||
group_names = NameDictionary::Add(
|
||||
isolate, group_names, name, capture_indices, PropertyDetails::Empty());
|
||||
}
|
||||
|
||||
// Convert group_names to a JSObject and store at the groups property of the
|
||||
// result indices.
|
||||
Handle<FixedArrayBase> elements = isolate->factory()->empty_fixed_array();
|
||||
Handle<HeapObject> null =
|
||||
Handle<HeapObject>::cast(isolate->factory()->null_value());
|
||||
Handle<JSObject> js_group_names =
|
||||
isolate->factory()->NewSlowJSObjectWithPropertiesAndElements(
|
||||
null, group_names, elements);
|
||||
indices->RawFastPropertyAtPut(groups_index, *js_group_names);
|
||||
return indices;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
@ -199,59 +199,18 @@ DEFINE_OPERATORS_FOR_FLAGS(JSRegExp::Flags)
|
||||
// After creation the result must be treated as a JSArray in all regards.
|
||||
class JSRegExpResult : public JSArray {
|
||||
public:
|
||||
DECL_CAST(JSRegExpResult)
|
||||
|
||||
// TODO(joshualitt): We would like to add printers and verifiers to
|
||||
// JSRegExpResult, and maybe JSRegExpResultIndices, but both have the same
|
||||
// instance type as JSArray.
|
||||
|
||||
// cached_indices_or_match_info and names, are used to construct the
|
||||
// JSRegExpResultIndices returned from the indices property lazily.
|
||||
DECL_ACCESSORS(cached_indices_or_match_info, Object)
|
||||
DECL_ACCESSORS(names, Object)
|
||||
|
||||
// Layout description.
|
||||
DEFINE_FIELD_OFFSET_CONSTANTS(JSArray::kSize,
|
||||
TORQUE_GENERATED_JSREG_EXP_RESULT_FIELDS)
|
||||
|
||||
static Handle<JSArray> GetAndCacheIndices(
|
||||
Isolate* isolate, Handle<JSRegExpResult> regexp_result);
|
||||
|
||||
// Indices of in-object properties.
|
||||
static const int kIndexIndex = 0;
|
||||
static const int kInputIndex = 1;
|
||||
static const int kGroupsIndex = 2;
|
||||
static const int kInObjectPropertyCount = 3;
|
||||
|
||||
OBJECT_CONSTRUCTORS(JSRegExpResult, JSArray);
|
||||
};
|
||||
|
||||
// JSRegExpResultIndices is just a JSArray with a specific initial map.
|
||||
// This initial map adds in-object properties for "group"
|
||||
// properties, as assigned by RegExp.prototype.exec, which allows
|
||||
// faster creation of RegExp exec results.
|
||||
// This class just holds constants used when creating the result.
|
||||
// After creation the result must be treated as a JSArray in all regards.
|
||||
class JSRegExpResultIndices : public JSArray {
|
||||
public:
|
||||
DECL_CAST(JSRegExpResultIndices)
|
||||
|
||||
// Layout description.
|
||||
DEFINE_FIELD_OFFSET_CONSTANTS(
|
||||
JSArray::kSize, TORQUE_GENERATED_JSREG_EXP_RESULT_INDICES_FIELDS)
|
||||
|
||||
static Handle<JSRegExpResultIndices> BuildIndices(
|
||||
Isolate* isolate, Handle<RegExpMatchInfo> match_info,
|
||||
Handle<Object> maybe_names);
|
||||
|
||||
// Indices of in-object properties.
|
||||
static const int kGroupsIndex = 0;
|
||||
static const int kInObjectPropertyCount = 1;
|
||||
|
||||
// Descriptor index of groups.
|
||||
static const int kGroupsDescriptorIndex = 1;
|
||||
|
||||
OBJECT_CONSTRUCTORS(JSRegExpResultIndices, JSArray);
|
||||
private:
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(JSRegExpResult);
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
@ -158,7 +158,6 @@ class ZoneForwardList;
|
||||
V(JSReceiver) \
|
||||
V(JSRegExp) \
|
||||
V(JSRegExpResult) \
|
||||
V(JSRegExpResultIndices) \
|
||||
V(JSRegExpStringIterator) \
|
||||
V(JSSet) \
|
||||
V(JSSetIterator) \
|
||||
|
@ -1,105 +0,0 @@
|
||||
// Copyright 2019 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
//
|
||||
// Flags: --harmony-regexp-match-indices
|
||||
|
||||
// Sanity test.
|
||||
{
|
||||
const re = /a+(?<Z>z)?/;
|
||||
const m = re.exec("xaaaz");
|
||||
|
||||
assertEquals(m.indices, [[1, 5], [4, 5]]);
|
||||
assertEquals(m.indices.groups, {'Z': [4, 5]})
|
||||
}
|
||||
|
||||
// Capture groups that are not matched return `undefined`.
|
||||
{
|
||||
const re = /a+(?<Z>z)?/;
|
||||
const m = re.exec("xaaay");
|
||||
|
||||
assertEquals(m.indices, [[1, 4], undefined]);
|
||||
assertEquals(m.indices.groups, {'Z': undefined});
|
||||
}
|
||||
|
||||
// Two capture groups.
|
||||
{
|
||||
const re = /a+(?<A>zz)?(?<B>ii)?/;
|
||||
const m = re.exec("xaaazzii");
|
||||
|
||||
assertEquals(m.indices, [[1, 8], [4, 6], [6, 8]]);
|
||||
assertEquals(m.indices.groups, {'A': [4, 6], 'B': [6, 8]});
|
||||
}
|
||||
|
||||
// No capture groups.
|
||||
{
|
||||
const re = /a+/;
|
||||
const m = re.exec("xaaazzii");
|
||||
|
||||
assertEquals(m.indices [[1, 4]]);
|
||||
assertEquals(m.indices.groups, undefined);
|
||||
}
|
||||
|
||||
// No match.
|
||||
{
|
||||
const re = /a+/;
|
||||
const m = re.exec("xzzii");
|
||||
|
||||
assertEquals(null, m);
|
||||
}
|
||||
|
||||
// Unnamed capture groups.
|
||||
{
|
||||
const re = /a+(z)?/;
|
||||
const m = re.exec("xaaaz")
|
||||
|
||||
assertEquals(m.indices, [[1, 5], [4, 5]]);
|
||||
assertEquals(m.indices.groups, undefined)
|
||||
}
|
||||
|
||||
// Named and unnamed capture groups.
|
||||
{
|
||||
const re = /a+(z)?(?<Y>y)?/;
|
||||
const m = re.exec("xaaazyy")
|
||||
|
||||
assertEquals(m.indices, [[1, 6], [4, 5], [5, 6]]);
|
||||
assertEquals(m.indices.groups, {'Y': [5, 6]})
|
||||
}
|
||||
|
||||
|
||||
// Verify property overwrite.
|
||||
{
|
||||
const re = /a+(?<Z>z)?/;
|
||||
const m = re.exec("xaaaz");
|
||||
|
||||
m.indices = null;
|
||||
assertEquals(null, m.indices);
|
||||
}
|
||||
|
||||
// Mess with array prototype, we should still do the right thing.
|
||||
{
|
||||
Object.defineProperty(Array.prototype, "groups", {
|
||||
get: () => {
|
||||
assertUnreachable();
|
||||
return null;
|
||||
},
|
||||
set: (x) => {
|
||||
assertUnreachable();
|
||||
}
|
||||
});
|
||||
|
||||
Object.defineProperty(Array.prototype, "0", {
|
||||
get: () => {
|
||||
assertUnreachable();
|
||||
return null;
|
||||
},
|
||||
set: (x) => {
|
||||
assertUnreachable();
|
||||
}
|
||||
});
|
||||
|
||||
const re = /a+(?<Z>z)?/;
|
||||
const m = re.exec("xaaaz");
|
||||
|
||||
assertEquals(m.indices.groups, {'Z': [4, 5]})
|
||||
}
|
@ -291,54 +291,54 @@ KNOWN_MAPS = {
|
||||
("read_only_space", 0x023a1): (87, "EnumCacheMap"),
|
||||
("read_only_space", 0x02441): (82, "ArrayBoilerplateDescriptionMap"),
|
||||
("read_only_space", 0x02631): (90, "InterceptorInfoMap"),
|
||||
("read_only_space", 0x04ec9): (77, "AccessCheckInfoMap"),
|
||||
("read_only_space", 0x04f19): (78, "AccessorInfoMap"),
|
||||
("read_only_space", 0x04f69): (79, "AccessorPairMap"),
|
||||
("read_only_space", 0x04fb9): (80, "AliasedArgumentsEntryMap"),
|
||||
("read_only_space", 0x05009): (81, "AllocationMementoMap"),
|
||||
("read_only_space", 0x05059): (83, "AsmWasmDataMap"),
|
||||
("read_only_space", 0x050a9): (84, "AsyncGeneratorRequestMap"),
|
||||
("read_only_space", 0x050f9): (85, "ClassPositionsMap"),
|
||||
("read_only_space", 0x05149): (86, "DebugInfoMap"),
|
||||
("read_only_space", 0x05199): (88, "FunctionTemplateInfoMap"),
|
||||
("read_only_space", 0x051e9): (89, "FunctionTemplateRareDataMap"),
|
||||
("read_only_space", 0x05239): (91, "InterpreterDataMap"),
|
||||
("read_only_space", 0x05289): (92, "ObjectTemplateInfoMap"),
|
||||
("read_only_space", 0x052d9): (93, "PromiseCapabilityMap"),
|
||||
("read_only_space", 0x05329): (94, "PromiseReactionMap"),
|
||||
("read_only_space", 0x05379): (95, "PrototypeInfoMap"),
|
||||
("read_only_space", 0x053c9): (96, "ScriptMap"),
|
||||
("read_only_space", 0x05419): (97, "SourcePositionTableWithFrameCacheMap"),
|
||||
("read_only_space", 0x05469): (98, "SourceTextModuleInfoEntryMap"),
|
||||
("read_only_space", 0x054b9): (99, "StackFrameInfoMap"),
|
||||
("read_only_space", 0x05509): (100, "StackTraceFrameMap"),
|
||||
("read_only_space", 0x05559): (101, "TemplateObjectDescriptionMap"),
|
||||
("read_only_space", 0x055a9): (102, "Tuple2Map"),
|
||||
("read_only_space", 0x055f9): (103, "Tuple3Map"),
|
||||
("read_only_space", 0x05649): (104, "WasmCapiFunctionDataMap"),
|
||||
("read_only_space", 0x05699): (105, "WasmDebugInfoMap"),
|
||||
("read_only_space", 0x056e9): (106, "WasmExceptionTagMap"),
|
||||
("read_only_space", 0x05739): (107, "WasmExportedFunctionDataMap"),
|
||||
("read_only_space", 0x05789): (108, "WasmIndirectFunctionTableMap"),
|
||||
("read_only_space", 0x057d9): (109, "WasmJSFunctionDataMap"),
|
||||
("read_only_space", 0x05829): (110, "CallableTaskMap"),
|
||||
("read_only_space", 0x05879): (111, "CallbackTaskMap"),
|
||||
("read_only_space", 0x058c9): (112, "PromiseFulfillReactionJobTaskMap"),
|
||||
("read_only_space", 0x05919): (113, "PromiseRejectReactionJobTaskMap"),
|
||||
("read_only_space", 0x05969): (114, "PromiseResolveThenableJobTaskMap"),
|
||||
("read_only_space", 0x059b9): (115, "InternalClassMap"),
|
||||
("read_only_space", 0x05a09): (116, "SmiPairMap"),
|
||||
("read_only_space", 0x05a59): (117, "SmiBoxMap"),
|
||||
("read_only_space", 0x05aa9): (118, "SortStateMap"),
|
||||
("read_only_space", 0x05af9): (121, "AllocationSiteWithWeakNextMap"),
|
||||
("read_only_space", 0x05b49): (121, "AllocationSiteWithoutWeakNextMap"),
|
||||
("read_only_space", 0x05b99): (156, "LoadHandler1Map"),
|
||||
("read_only_space", 0x05be9): (156, "LoadHandler2Map"),
|
||||
("read_only_space", 0x05c39): (156, "LoadHandler3Map"),
|
||||
("read_only_space", 0x05c89): (164, "StoreHandler0Map"),
|
||||
("read_only_space", 0x05cd9): (164, "StoreHandler1Map"),
|
||||
("read_only_space", 0x05d29): (164, "StoreHandler2Map"),
|
||||
("read_only_space", 0x05d79): (164, "StoreHandler3Map"),
|
||||
("read_only_space", 0x04eb1): (77, "AccessCheckInfoMap"),
|
||||
("read_only_space", 0x04f01): (78, "AccessorInfoMap"),
|
||||
("read_only_space", 0x04f51): (79, "AccessorPairMap"),
|
||||
("read_only_space", 0x04fa1): (80, "AliasedArgumentsEntryMap"),
|
||||
("read_only_space", 0x04ff1): (81, "AllocationMementoMap"),
|
||||
("read_only_space", 0x05041): (83, "AsmWasmDataMap"),
|
||||
("read_only_space", 0x05091): (84, "AsyncGeneratorRequestMap"),
|
||||
("read_only_space", 0x050e1): (85, "ClassPositionsMap"),
|
||||
("read_only_space", 0x05131): (86, "DebugInfoMap"),
|
||||
("read_only_space", 0x05181): (88, "FunctionTemplateInfoMap"),
|
||||
("read_only_space", 0x051d1): (89, "FunctionTemplateRareDataMap"),
|
||||
("read_only_space", 0x05221): (91, "InterpreterDataMap"),
|
||||
("read_only_space", 0x05271): (92, "ObjectTemplateInfoMap"),
|
||||
("read_only_space", 0x052c1): (93, "PromiseCapabilityMap"),
|
||||
("read_only_space", 0x05311): (94, "PromiseReactionMap"),
|
||||
("read_only_space", 0x05361): (95, "PrototypeInfoMap"),
|
||||
("read_only_space", 0x053b1): (96, "ScriptMap"),
|
||||
("read_only_space", 0x05401): (97, "SourcePositionTableWithFrameCacheMap"),
|
||||
("read_only_space", 0x05451): (98, "SourceTextModuleInfoEntryMap"),
|
||||
("read_only_space", 0x054a1): (99, "StackFrameInfoMap"),
|
||||
("read_only_space", 0x054f1): (100, "StackTraceFrameMap"),
|
||||
("read_only_space", 0x05541): (101, "TemplateObjectDescriptionMap"),
|
||||
("read_only_space", 0x05591): (102, "Tuple2Map"),
|
||||
("read_only_space", 0x055e1): (103, "Tuple3Map"),
|
||||
("read_only_space", 0x05631): (104, "WasmCapiFunctionDataMap"),
|
||||
("read_only_space", 0x05681): (105, "WasmDebugInfoMap"),
|
||||
("read_only_space", 0x056d1): (106, "WasmExceptionTagMap"),
|
||||
("read_only_space", 0x05721): (107, "WasmExportedFunctionDataMap"),
|
||||
("read_only_space", 0x05771): (108, "WasmIndirectFunctionTableMap"),
|
||||
("read_only_space", 0x057c1): (109, "WasmJSFunctionDataMap"),
|
||||
("read_only_space", 0x05811): (110, "CallableTaskMap"),
|
||||
("read_only_space", 0x05861): (111, "CallbackTaskMap"),
|
||||
("read_only_space", 0x058b1): (112, "PromiseFulfillReactionJobTaskMap"),
|
||||
("read_only_space", 0x05901): (113, "PromiseRejectReactionJobTaskMap"),
|
||||
("read_only_space", 0x05951): (114, "PromiseResolveThenableJobTaskMap"),
|
||||
("read_only_space", 0x059a1): (115, "InternalClassMap"),
|
||||
("read_only_space", 0x059f1): (116, "SmiPairMap"),
|
||||
("read_only_space", 0x05a41): (117, "SmiBoxMap"),
|
||||
("read_only_space", 0x05a91): (118, "SortStateMap"),
|
||||
("read_only_space", 0x05ae1): (121, "AllocationSiteWithWeakNextMap"),
|
||||
("read_only_space", 0x05b31): (121, "AllocationSiteWithoutWeakNextMap"),
|
||||
("read_only_space", 0x05b81): (156, "LoadHandler1Map"),
|
||||
("read_only_space", 0x05bd1): (156, "LoadHandler2Map"),
|
||||
("read_only_space", 0x05c21): (156, "LoadHandler3Map"),
|
||||
("read_only_space", 0x05c71): (164, "StoreHandler0Map"),
|
||||
("read_only_space", 0x05cc1): (164, "StoreHandler1Map"),
|
||||
("read_only_space", 0x05d11): (164, "StoreHandler2Map"),
|
||||
("read_only_space", 0x05d61): (164, "StoreHandler3Map"),
|
||||
("map_space", 0x00119): (1057, "ExternalMap"),
|
||||
("map_space", 0x00169): (1073, "JSMessageObjectMap"),
|
||||
}
|
||||
@ -398,30 +398,29 @@ KNOWN_OBJECTS = {
|
||||
("old_space", 0x00429): "FunctionNameAccessor",
|
||||
("old_space", 0x00499): "FunctionLengthAccessor",
|
||||
("old_space", 0x00509): "FunctionPrototypeAccessor",
|
||||
("old_space", 0x00579): "RegExpResultIndicesAccessor",
|
||||
("old_space", 0x005e9): "StringLengthAccessor",
|
||||
("old_space", 0x00659): "InvalidPrototypeValidityCell",
|
||||
("old_space", 0x00669): "EmptyScript",
|
||||
("old_space", 0x006e9): "ManyClosuresCell",
|
||||
("old_space", 0x00701): "ArrayConstructorProtector",
|
||||
("old_space", 0x00711): "NoElementsProtector",
|
||||
("old_space", 0x00739): "IsConcatSpreadableProtector",
|
||||
("old_space", 0x00749): "ArraySpeciesProtector",
|
||||
("old_space", 0x00771): "TypedArraySpeciesProtector",
|
||||
("old_space", 0x00799): "PromiseSpeciesProtector",
|
||||
("old_space", 0x007c1): "StringLengthProtector",
|
||||
("old_space", 0x007d1): "ArrayIteratorProtector",
|
||||
("old_space", 0x007f9): "ArrayBufferDetachingProtector",
|
||||
("old_space", 0x00821): "PromiseHookProtector",
|
||||
("old_space", 0x00849): "PromiseResolveProtector",
|
||||
("old_space", 0x00859): "MapIteratorProtector",
|
||||
("old_space", 0x00881): "PromiseThenProtector",
|
||||
("old_space", 0x008a9): "SetIteratorProtector",
|
||||
("old_space", 0x008d1): "StringIteratorProtector",
|
||||
("old_space", 0x008f9): "SingleCharacterStringCache",
|
||||
("old_space", 0x01109): "StringSplitCache",
|
||||
("old_space", 0x01919): "RegExpMultipleCache",
|
||||
("old_space", 0x02129): "BuiltinsConstantsTable",
|
||||
("old_space", 0x00579): "StringLengthAccessor",
|
||||
("old_space", 0x005e9): "InvalidPrototypeValidityCell",
|
||||
("old_space", 0x005f9): "EmptyScript",
|
||||
("old_space", 0x00679): "ManyClosuresCell",
|
||||
("old_space", 0x00691): "ArrayConstructorProtector",
|
||||
("old_space", 0x006a1): "NoElementsProtector",
|
||||
("old_space", 0x006c9): "IsConcatSpreadableProtector",
|
||||
("old_space", 0x006d9): "ArraySpeciesProtector",
|
||||
("old_space", 0x00701): "TypedArraySpeciesProtector",
|
||||
("old_space", 0x00729): "PromiseSpeciesProtector",
|
||||
("old_space", 0x00751): "StringLengthProtector",
|
||||
("old_space", 0x00761): "ArrayIteratorProtector",
|
||||
("old_space", 0x00789): "ArrayBufferDetachingProtector",
|
||||
("old_space", 0x007b1): "PromiseHookProtector",
|
||||
("old_space", 0x007d9): "PromiseResolveProtector",
|
||||
("old_space", 0x007e9): "MapIteratorProtector",
|
||||
("old_space", 0x00811): "PromiseThenProtector",
|
||||
("old_space", 0x00839): "SetIteratorProtector",
|
||||
("old_space", 0x00861): "StringIteratorProtector",
|
||||
("old_space", 0x00889): "SingleCharacterStringCache",
|
||||
("old_space", 0x01099): "StringSplitCache",
|
||||
("old_space", 0x018a9): "RegExpMultipleCache",
|
||||
("old_space", 0x020b9): "BuiltinsConstantsTable",
|
||||
}
|
||||
|
||||
# List of known V8 Frame Markers.
|
||||
|
Loading…
Reference in New Issue
Block a user