[regexp] Properly flatten string during initialization

This fixes an incorrect usage of String::Flatten in EscapeRegExpSource.

It also adds %ConstructConsString (to easily and reliably construct cons
strings in tests) and Factory::NewConsString (to enable guaranteed cons
string construction without preemptive flattening attempts).

BUG=chromium:698790

Review-Url: https://codereview.chromium.org/2736383003
Cr-Commit-Position: refs/heads/master@{#43686}
This commit is contained in:
jgruber 2017-03-09 04:25:19 -08:00 committed by Commit bot
parent e9a25e287d
commit 5002a4a961
7 changed files with 56 additions and 5 deletions

View File

@ -711,10 +711,20 @@ MaybeHandle<String> Factory::NewConsString(Handle<String> left,
NewRawTwoByteString(length).ToHandleChecked(), left, right);
}
bool one_byte = (is_one_byte || is_one_byte_data_in_two_byte_string);
return NewConsString(left, right, length, one_byte);
}
Handle<String> Factory::NewConsString(Handle<String> left, Handle<String> right,
int length, bool one_byte) {
DCHECK(!left->IsThinString());
DCHECK(!right->IsThinString());
DCHECK_GE(length, ConsString::kMinLength);
DCHECK_LE(length, String::kMaxLength);
Handle<ConsString> result =
(is_one_byte || is_one_byte_data_in_two_byte_string)
? New<ConsString>(cons_one_byte_string_map(), NEW_SPACE)
: New<ConsString>(cons_string_map(), NEW_SPACE);
one_byte ? New<ConsString>(cons_one_byte_string_map(), NEW_SPACE)
: New<ConsString>(cons_string_map(), NEW_SPACE);
DisallowHeapAllocation no_gc;
WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc);

View File

@ -252,6 +252,10 @@ class V8_EXPORT_PRIVATE Factory final {
MUST_USE_RESULT MaybeHandle<String> NewConsString(Handle<String> left,
Handle<String> right);
MUST_USE_RESULT Handle<String> NewConsString(Handle<String> left,
Handle<String> right, int length,
bool one_byte);
// Create or lookup a single characters tring made up of a utf16 surrogate
// pair.
Handle<String> NewSurrogatePairString(uint16_t lead, uint16_t trail);

View File

@ -16111,7 +16111,7 @@ inline Handle<StringType> WriteEscapedRegExpSource(Handle<String> source,
MaybeHandle<String> EscapeRegExpSource(Isolate* isolate,
Handle<String> source) {
String::Flatten(source);
DCHECK(source->IsFlat());
if (source->length() == 0) return isolate->factory()->query_colon_string();
bool one_byte = source->IsOneByteRepresentationUnderneath();
int escapes = one_byte ? CountRequiredEscapes<uint8_t>(source)
@ -16160,6 +16160,8 @@ MaybeHandle<JSRegExp> JSRegExp::Initialize(Handle<JSRegExp> regexp,
// suggested by ECMA-262, 5th, section 15.10.4.1.
if (source->length() == 0) source = factory->query_colon_string();
source = String::Flatten(source);
Handle<String> escaped_source;
ASSIGN_RETURN_ON_EXCEPTION(isolate, escaped_source,
EscapeRegExpSource(isolate, source), JSRegExp);

View File

@ -135,6 +135,8 @@ static bool HasFewDifferentCharacters(Handle<String> pattern) {
MaybeHandle<Object> RegExpImpl::Compile(Handle<JSRegExp> re,
Handle<String> pattern,
JSRegExp::Flags flags) {
DCHECK(pattern->IsFlat());
Isolate* isolate = re->GetIsolate();
Zone zone(isolate->allocator(), ZONE_NAME);
CompilationCache* compilation_cache = isolate->compilation_cache();
@ -145,7 +147,7 @@ MaybeHandle<Object> RegExpImpl::Compile(Handle<JSRegExp> re,
re->set_data(*cached);
return re;
}
pattern = String::Flatten(pattern);
PostponeInterruptsScope postpone(isolate);
RegExpCompileData parse_result;
FlatStringReader reader(isolate, pattern);

View File

@ -71,6 +71,20 @@ RUNTIME_FUNCTION(Runtime_ConstructDouble) {
return *isolate->factory()->NewNumber(uint64_to_double(result));
}
RUNTIME_FUNCTION(Runtime_ConstructConsString) {
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
CONVERT_ARG_HANDLE_CHECKED(String, left, 0);
CONVERT_ARG_HANDLE_CHECKED(String, right, 1);
CHECK(left->IsOneByteRepresentation());
CHECK(right->IsOneByteRepresentation());
const bool kIsOneByte = true;
const int length = left->length() + right->length();
return *isolate->factory()->NewConsString(left, right, length, kIsOneByte);
}
RUNTIME_FUNCTION(Runtime_DeoptimizeFunction) {
HandleScope scope(isolate);
DCHECK_EQ(1, args.length());

View File

@ -549,6 +549,7 @@ namespace internal {
#define FOR_EACH_INTRINSIC_TEST(F) \
F(ConstructDouble, 2, 1) \
F(ConstructConsString, 2, 1) \
F(DeoptimizeFunction, 1, 1) \
F(DeoptimizeNow, 0, 1) \
F(RunningInSimulator, 0, 1) \

View File

@ -0,0 +1,18 @@
// Copyright 2017 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: --allow-natives-syntax --turbo
// Call RegExp constructor with a cons string.
var cons_string = %ConstructConsString("", "aaaaaaaaaaaaaa");
new RegExp(cons_string);
// Same thing but using TF lowering.
function make_cons_string(s) { return s + "aaaaaaaaaaaaaa"; }
make_cons_string("");
%OptimizeFunctionOnNextCall(make_cons_string);
var cons_str = make_cons_string("");
new RegExp(cons_str);