diff options
Diffstat (limited to 'deps/v8/src/runtime/runtime-regexp.cc')
-rw-r--r-- | deps/v8/src/runtime/runtime-regexp.cc | 63 |
1 files changed, 62 insertions, 1 deletions
diff --git a/deps/v8/src/runtime/runtime-regexp.cc b/deps/v8/src/runtime/runtime-regexp.cc index 5846881f90..478573a68d 100644 --- a/deps/v8/src/runtime/runtime-regexp.cc +++ b/deps/v8/src/runtime/runtime-regexp.cc @@ -638,7 +638,7 @@ MUST_USE_RESULT static Object* StringReplaceGlobalRegExpWithEmptyString( // thread can not get confused with the filler creation. No synchronization // needed. heap->CreateFillerObjectAt(end_of_string, delta); - heap->AdjustLiveBytes(answer->address(), -delta, Heap::FROM_MUTATOR); + heap->AdjustLiveBytes(answer->address(), -delta, Heap::CONCURRENT_TO_SWEEPER); return *answer; } @@ -844,6 +844,60 @@ static JSRegExp::Flags RegExpFlagsFromString(Handle<String> flags, } +template <typename Char> +inline int CountRequiredEscapes(Handle<String> source) { + DisallowHeapAllocation no_gc; + int escapes = 0; + Vector<const Char> src = source->GetCharVector<Char>(); + for (int i = 0; i < src.length(); i++) { + if (src[i] == '/' && (i == 0 || src[i - 1] != '\\')) escapes++; + } + return escapes; +} + + +template <typename Char, typename StringType> +inline Handle<StringType> WriteEscapedRegExpSource(Handle<String> source, + Handle<StringType> result) { + DisallowHeapAllocation no_gc; + Vector<const Char> src = source->GetCharVector<Char>(); + Vector<Char> dst(result->GetChars(), result->length()); + int s = 0; + int d = 0; + while (s < src.length()) { + if (src[s] == '/' && (s == 0 || src[s - 1] != '\\')) dst[d++] = '\\'; + dst[d++] = src[s++]; + } + DCHECK_EQ(result->length(), d); + return result; +} + + +MaybeHandle<String> EscapeRegExpSource(Isolate* isolate, + Handle<String> source) { + String::Flatten(source); + if (source->length() == 0) return isolate->factory()->query_colon_string(); + bool one_byte = source->IsOneByteRepresentationUnderneath(); + int escapes = one_byte ? CountRequiredEscapes<uint8_t>(source) + : CountRequiredEscapes<uc16>(source); + if (escapes == 0) return source; + int length = source->length() + escapes; + if (one_byte) { + Handle<SeqOneByteString> result; + ASSIGN_RETURN_ON_EXCEPTION(isolate, result, + isolate->factory()->NewRawOneByteString(length), + String); + return WriteEscapedRegExpSource<uint8_t>(source, result); + } else { + Handle<SeqTwoByteString> result; + ASSIGN_RETURN_ON_EXCEPTION(isolate, result, + isolate->factory()->NewRawTwoByteString(length), + String); + return WriteEscapedRegExpSource<uc16>(source, result); + } +} + + RUNTIME_FUNCTION(Runtime_RegExpInitializeAndCompile) { HandleScope scope(isolate); DCHECK(args.length() == 3); @@ -865,6 +919,10 @@ RUNTIME_FUNCTION(Runtime_RegExpInitializeAndCompile) { isolate, NewSyntaxError("invalid_regexp_flags", args)); } + Handle<String> escaped_source; + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, escaped_source, + EscapeRegExpSource(isolate, source)); + Handle<Object> global = factory->ToBoolean(flags.is_global()); Handle<Object> ignore_case = factory->ToBoolean(flags.is_ignore_case()); Handle<Object> multiline = factory->ToBoolean(flags.is_multiline()); @@ -877,6 +935,7 @@ RUNTIME_FUNCTION(Runtime_RegExpInitializeAndCompile) { constructor->IsJSFunction() && JSFunction::cast(constructor)->initial_map() == map) { // If we still have the original map, set in-object properties directly. + regexp->InObjectPropertyAtPut(JSRegExp::kSourceFieldIndex, *escaped_source); // Both true and false are immovable immortal objects so no need for write // barrier. regexp->InObjectPropertyAtPut(JSRegExp::kGlobalFieldIndex, *global, @@ -898,6 +957,8 @@ RUNTIME_FUNCTION(Runtime_RegExpInitializeAndCompile) { PropertyAttributes writable = static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE); Handle<Object> zero(Smi::FromInt(0), isolate); + JSObject::SetOwnPropertyIgnoreAttributes(regexp, factory->source_string(), + escaped_source, final).Check(); JSObject::SetOwnPropertyIgnoreAttributes(regexp, factory->global_string(), global, final).Check(); JSObject::SetOwnPropertyIgnoreAttributes( |