aboutsummaryrefslogtreecommitdiff
path: root/deps/v8/src/regexp
diff options
context:
space:
mode:
authorMichaël Zasso <targos@protonmail.com>2017-02-14 11:27:26 +0100
committerMichaël Zasso <targos@protonmail.com>2017-02-22 15:55:42 +0100
commit7a77daf24344db7942e34c962b0f1ee729ab7af5 (patch)
treee7cbe7bf4e2f4b802a8f5bc18336c546cd6a0d7f /deps/v8/src/regexp
parent5f08871ee93ea739148cc49e0f7679e33c70295a (diff)
downloadandroid-node-v8-7a77daf24344db7942e34c962b0f1ee729ab7af5.tar.gz
android-node-v8-7a77daf24344db7942e34c962b0f1ee729ab7af5.tar.bz2
android-node-v8-7a77daf24344db7942e34c962b0f1ee729ab7af5.zip
deps: update V8 to 5.6.326.55
PR-URL: https://github.com/nodejs/node/pull/10992 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Diffstat (limited to 'deps/v8/src/regexp')
-rw-r--r--deps/v8/src/regexp/OWNERS4
-rw-r--r--deps/v8/src/regexp/jsregexp.cc113
-rw-r--r--deps/v8/src/regexp/jsregexp.h55
-rw-r--r--deps/v8/src/regexp/regexp-macro-assembler-tracer.cc6
-rw-r--r--deps/v8/src/regexp/regexp-parser.cc2
-rw-r--r--deps/v8/src/regexp/regexp-utils.cc192
-rw-r--r--deps/v8/src/regexp/regexp-utils.h52
7 files changed, 312 insertions, 112 deletions
diff --git a/deps/v8/src/regexp/OWNERS b/deps/v8/src/regexp/OWNERS
index d9d588df6c..c493afa8f0 100644
--- a/deps/v8/src/regexp/OWNERS
+++ b/deps/v8/src/regexp/OWNERS
@@ -1,6 +1,4 @@
set noparent
-jochen@chromium.org
-marja@chromium.org
-ulan@chromium.org
+jgruber@chromium.org
yangguo@chromium.org
diff --git a/deps/v8/src/regexp/jsregexp.cc b/deps/v8/src/regexp/jsregexp.cc
index 96a778cfb7..f0abc9a8b3 100644
--- a/deps/v8/src/regexp/jsregexp.cc
+++ b/deps/v8/src/regexp/jsregexp.cc
@@ -136,16 +136,12 @@ MaybeHandle<Object> RegExpImpl::Compile(Handle<JSRegExp> re,
Handle<String> pattern,
JSRegExp::Flags flags) {
Isolate* isolate = re->GetIsolate();
- Zone zone(isolate->allocator());
+ Zone zone(isolate->allocator(), ZONE_NAME);
CompilationCache* compilation_cache = isolate->compilation_cache();
MaybeHandle<FixedArray> maybe_cached =
compilation_cache->LookupRegExp(pattern, flags);
Handle<FixedArray> cached;
- bool in_cache = maybe_cached.ToHandle(&cached);
- LOG(isolate, RegExpCompileEvent(re, in_cache));
-
- Handle<Object> result;
- if (in_cache) {
+ if (maybe_cached.ToHandle(&cached)) {
re->set_data(*cached);
return re;
}
@@ -194,7 +190,7 @@ MaybeHandle<Object> RegExpImpl::Compile(Handle<JSRegExp> re,
MaybeHandle<Object> RegExpImpl::Exec(Handle<JSRegExp> regexp,
Handle<String> subject, int index,
- Handle<JSObject> last_match_info) {
+ Handle<RegExpMatchInfo> last_match_info) {
switch (regexp->TypeTag()) {
case JSRegExp::ATOM:
return AtomExec(regexp, subject, index, last_match_info);
@@ -222,17 +218,14 @@ void RegExpImpl::AtomCompile(Handle<JSRegExp> re,
match_pattern);
}
-
-static void SetAtomLastCapture(FixedArray* array,
- String* subject,
- int from,
- int to) {
- SealHandleScope shs(array->GetIsolate());
- RegExpImpl::SetLastCaptureCount(array, 2);
- RegExpImpl::SetLastSubject(array, subject);
- RegExpImpl::SetLastInput(array, subject);
- RegExpImpl::SetCapture(array, 0, from);
- RegExpImpl::SetCapture(array, 1, to);
+static void SetAtomLastCapture(Handle<RegExpMatchInfo> last_match_info,
+ String* subject, int from, int to) {
+ SealHandleScope shs(last_match_info->GetIsolate());
+ last_match_info->SetNumberOfCaptureRegisters(2);
+ last_match_info->SetLastSubject(subject);
+ last_match_info->SetLastInput(subject);
+ last_match_info->SetCapture(0, from);
+ last_match_info->SetCapture(1, to);
}
@@ -289,7 +282,7 @@ int RegExpImpl::AtomExecRaw(Handle<JSRegExp> regexp,
Handle<Object> RegExpImpl::AtomExec(Handle<JSRegExp> re, Handle<String> subject,
int index,
- Handle<JSObject> last_match_info) {
+ Handle<RegExpMatchInfo> last_match_info) {
Isolate* isolate = re->GetIsolate();
static const int kNumRegisters = 2;
@@ -302,8 +295,8 @@ Handle<Object> RegExpImpl::AtomExec(Handle<JSRegExp> re, Handle<String> subject,
DCHECK_EQ(res, RegExpImpl::RE_SUCCESS);
SealHandleScope shs(isolate);
- FixedArray* array = FixedArray::cast(last_match_info->elements());
- SetAtomLastCapture(array, *subject, output_registers[0], output_registers[1]);
+ SetAtomLastCapture(last_match_info, *subject, output_registers[0],
+ output_registers[1]);
return last_match_info;
}
@@ -343,7 +336,7 @@ bool RegExpImpl::CompileIrregexp(Handle<JSRegExp> re,
bool is_one_byte) {
// Compile the RegExp.
Isolate* isolate = re->GetIsolate();
- Zone zone(isolate->allocator());
+ Zone zone(isolate->allocator(), ZONE_NAME);
PostponeInterruptsScope postpone(isolate);
// If we had a compilation error the last time this is saved at the
// saved code index.
@@ -417,7 +410,7 @@ void RegExpImpl::SetIrregexpMaxRegisterCount(FixedArray* re, int value) {
void RegExpImpl::SetIrregexpCaptureNameMap(FixedArray* re,
Handle<FixedArray> value) {
if (value.is_null()) {
- re->set(JSRegExp::kIrregexpCaptureNameMapIndex, Smi::FromInt(0));
+ re->set(JSRegExp::kIrregexpCaptureNameMapIndex, Smi::kZero);
} else {
re->set(JSRegExp::kIrregexpCaptureNameMapIndex, *value);
}
@@ -566,10 +559,9 @@ int RegExpImpl::IrregexpExecRaw(Handle<JSRegExp> regexp,
#endif // V8_INTERPRETED_REGEXP
}
-MaybeHandle<Object> RegExpImpl::IrregexpExec(Handle<JSRegExp> regexp,
- Handle<String> subject,
- int previous_index,
- Handle<JSObject> last_match_info) {
+MaybeHandle<Object> RegExpImpl::IrregexpExec(
+ Handle<JSRegExp> regexp, Handle<String> subject, int previous_index,
+ Handle<RegExpMatchInfo> last_match_info) {
Isolate* isolate = regexp->GetIsolate();
DCHECK_EQ(regexp->TypeTag(), JSRegExp::IRREGEXP);
@@ -613,31 +605,40 @@ MaybeHandle<Object> RegExpImpl::IrregexpExec(Handle<JSRegExp> regexp,
return isolate->factory()->null_value();
}
-static void EnsureSize(Handle<JSObject> array, uint32_t minimum_size) {
- if (static_cast<uint32_t>(array->elements()->length()) < minimum_size) {
- array->GetElementsAccessor()->GrowCapacityAndConvert(array, minimum_size);
- }
-}
+Handle<RegExpMatchInfo> RegExpImpl::SetLastMatchInfo(
+ Handle<RegExpMatchInfo> last_match_info, Handle<String> subject,
+ int capture_count, int32_t* match) {
+ // This is the only place where match infos can grow. If, after executing the
+ // regexp, RegExpExecStub finds that the match info is too small, it restarts
+ // execution in RegExpImpl::Exec, which finally grows the match info right
+ // here.
-Handle<JSObject> RegExpImpl::SetLastMatchInfo(Handle<JSObject> last_match_info,
- Handle<String> subject,
- int capture_count,
- int32_t* match) {
- DCHECK(last_match_info->HasFastObjectElements());
int capture_register_count = (capture_count + 1) * 2;
- EnsureSize(last_match_info, capture_register_count + kLastMatchOverhead);
+ Handle<RegExpMatchInfo> result =
+ RegExpMatchInfo::ReserveCaptures(last_match_info, capture_register_count);
+ result->SetNumberOfCaptureRegisters(capture_register_count);
+
+ if (*result != *last_match_info) {
+ // The match info has been reallocated, update the corresponding reference
+ // on the native context.
+ Isolate* isolate = last_match_info->GetIsolate();
+ if (*last_match_info == *isolate->regexp_last_match_info()) {
+ isolate->native_context()->set_regexp_last_match_info(*result);
+ } else if (*last_match_info == *isolate->regexp_internal_match_info()) {
+ isolate->native_context()->set_regexp_internal_match_info(*result);
+ }
+ }
+
DisallowHeapAllocation no_allocation;
- FixedArray* array = FixedArray::cast(last_match_info->elements());
if (match != NULL) {
for (int i = 0; i < capture_register_count; i += 2) {
- SetCapture(array, i, match[i]);
- SetCapture(array, i + 1, match[i + 1]);
+ result->SetCapture(i, match[i]);
+ result->SetCapture(i + 1, match[i + 1]);
}
}
- SetLastCaptureCount(array, capture_register_count);
- SetLastSubject(array, *subject);
- SetLastInput(array, *subject);
- return last_match_info;
+ result->SetLastSubject(*subject);
+ result->SetLastInput(*subject);
+ return result;
}
@@ -6781,10 +6782,10 @@ Object* RegExpResultsCache::Lookup(Heap* heap, String* key_string,
FixedArray** last_match_cache,
ResultsCacheType type) {
FixedArray* cache;
- if (!key_string->IsInternalizedString()) return Smi::FromInt(0);
+ if (!key_string->IsInternalizedString()) return Smi::kZero;
if (type == STRING_SPLIT_SUBSTRINGS) {
DCHECK(key_pattern->IsString());
- if (!key_pattern->IsInternalizedString()) return Smi::FromInt(0);
+ if (!key_pattern->IsInternalizedString()) return Smi::kZero;
cache = heap->string_split_cache();
} else {
DCHECK(type == REGEXP_MULTIPLE_INDICES);
@@ -6801,7 +6802,7 @@ Object* RegExpResultsCache::Lookup(Heap* heap, String* key_string,
((index + kArrayEntriesPerCacheEntry) & (kRegExpResultsCacheSize - 1));
if (cache->get(index + kStringOffset) != key_string ||
cache->get(index + kPatternOffset) != key_pattern) {
- return Smi::FromInt(0);
+ return Smi::kZero;
}
}
@@ -6831,7 +6832,7 @@ void RegExpResultsCache::Enter(Isolate* isolate, Handle<String> key_string,
uint32_t hash = key_string->Hash();
uint32_t index = ((hash & (kRegExpResultsCacheSize - 1)) &
~(kArrayEntriesPerCacheEntry - 1));
- if (cache->get(index + kStringOffset) == Smi::FromInt(0)) {
+ if (cache->get(index + kStringOffset) == Smi::kZero) {
cache->set(index + kStringOffset, *key_string);
cache->set(index + kPatternOffset, *key_pattern);
cache->set(index + kArrayOffset, *value_array);
@@ -6839,16 +6840,16 @@ void RegExpResultsCache::Enter(Isolate* isolate, Handle<String> key_string,
} else {
uint32_t index2 =
((index + kArrayEntriesPerCacheEntry) & (kRegExpResultsCacheSize - 1));
- if (cache->get(index2 + kStringOffset) == Smi::FromInt(0)) {
+ if (cache->get(index2 + kStringOffset) == Smi::kZero) {
cache->set(index2 + kStringOffset, *key_string);
cache->set(index2 + kPatternOffset, *key_pattern);
cache->set(index2 + kArrayOffset, *value_array);
cache->set(index2 + kLastMatchOffset, *last_match_cache);
} else {
- cache->set(index2 + kStringOffset, Smi::FromInt(0));
- cache->set(index2 + kPatternOffset, Smi::FromInt(0));
- cache->set(index2 + kArrayOffset, Smi::FromInt(0));
- cache->set(index2 + kLastMatchOffset, Smi::FromInt(0));
+ cache->set(index2 + kStringOffset, Smi::kZero);
+ cache->set(index2 + kPatternOffset, Smi::kZero);
+ cache->set(index2 + kArrayOffset, Smi::kZero);
+ cache->set(index2 + kLastMatchOffset, Smi::kZero);
cache->set(index + kStringOffset, *key_string);
cache->set(index + kPatternOffset, *key_pattern);
cache->set(index + kArrayOffset, *value_array);
@@ -6865,13 +6866,13 @@ void RegExpResultsCache::Enter(Isolate* isolate, Handle<String> key_string,
}
}
// Convert backing store to a copy-on-write array.
- value_array->set_map_no_write_barrier(*factory->fixed_cow_array_map());
+ value_array->set_map_no_write_barrier(isolate->heap()->fixed_cow_array_map());
}
void RegExpResultsCache::Clear(FixedArray* cache) {
for (int i = 0; i < kRegExpResultsCacheSize; i++) {
- cache->set(i, Smi::FromInt(0));
+ cache->set(i, Smi::kZero);
}
}
diff --git a/deps/v8/src/regexp/jsregexp.h b/deps/v8/src/regexp/jsregexp.h
index 8118889966..b2e84ba4f3 100644
--- a/deps/v8/src/regexp/jsregexp.h
+++ b/deps/v8/src/regexp/jsregexp.h
@@ -48,7 +48,7 @@ class RegExpImpl {
// This function calls the garbage collector if necessary.
V8_EXPORT_PRIVATE MUST_USE_RESULT static MaybeHandle<Object> Exec(
Handle<JSRegExp> regexp, Handle<String> subject, int index,
- Handle<JSObject> lastMatchInfo);
+ Handle<RegExpMatchInfo> last_match_info);
// Prepares a JSRegExp object with Irregexp-specific data.
static void IrregexpInitialize(Handle<JSRegExp> re,
@@ -71,7 +71,7 @@ class RegExpImpl {
static Handle<Object> AtomExec(Handle<JSRegExp> regexp,
Handle<String> subject, int index,
- Handle<JSObject> lastMatchInfo);
+ Handle<RegExpMatchInfo> last_match_info);
enum IrregexpResult { RE_FAILURE = 0, RE_SUCCESS = 1, RE_EXCEPTION = -1 };
@@ -103,12 +103,12 @@ class RegExpImpl {
// Returns an empty handle in case of an exception.
MUST_USE_RESULT static MaybeHandle<Object> IrregexpExec(
Handle<JSRegExp> regexp, Handle<String> subject, int index,
- Handle<JSObject> lastMatchInfo);
+ Handle<RegExpMatchInfo> last_match_info);
// Set last match info. If match is NULL, then setting captures is omitted.
- static Handle<JSObject> SetLastMatchInfo(Handle<JSObject> last_match_info,
- Handle<String> subject,
- int capture_count, int32_t* match);
+ static Handle<RegExpMatchInfo> SetLastMatchInfo(
+ Handle<RegExpMatchInfo> last_match_info, Handle<String> subject,
+ int capture_count, int32_t* match);
class GlobalCache {
public:
@@ -142,49 +142,6 @@ class RegExpImpl {
Handle<String> subject_;
};
-
- // Array index in the lastMatchInfo array.
- static const int kLastCaptureCount = 0;
- static const int kLastSubject = 1;
- static const int kLastInput = 2;
- static const int kFirstCapture = 3;
- static const int kLastMatchOverhead = 3;
-
- // Direct offset into the lastMatchInfo array.
- static const int kLastCaptureCountOffset =
- FixedArray::kHeaderSize + kLastCaptureCount * kPointerSize;
- static const int kLastSubjectOffset =
- FixedArray::kHeaderSize + kLastSubject * kPointerSize;
- static const int kLastInputOffset =
- FixedArray::kHeaderSize + kLastInput * kPointerSize;
- static const int kFirstCaptureOffset =
- FixedArray::kHeaderSize + kFirstCapture * kPointerSize;
-
- // Used to access the lastMatchInfo array.
- static int GetCapture(FixedArray* array, int index) {
- return Smi::cast(array->get(index + kFirstCapture))->value();
- }
-
- static void SetLastCaptureCount(FixedArray* array, int to) {
- array->set(kLastCaptureCount, Smi::FromInt(to));
- }
-
- static void SetLastSubject(FixedArray* array, String* to) {
- array->set(kLastSubject, to);
- }
-
- static void SetLastInput(FixedArray* array, String* to) {
- array->set(kLastInput, to);
- }
-
- static void SetCapture(FixedArray* array, int index, int to) {
- array->set(index + kFirstCapture, Smi::FromInt(to));
- }
-
- static int GetLastCaptureCount(FixedArray* array) {
- return Smi::cast(array->get(kLastCaptureCount))->value();
- }
-
// For acting on the JSRegExp data FixedArray.
static int IrregexpMaxRegisterCount(FixedArray* re);
static void SetIrregexpMaxRegisterCount(FixedArray* re, int value);
diff --git a/deps/v8/src/regexp/regexp-macro-assembler-tracer.cc b/deps/v8/src/regexp/regexp-macro-assembler-tracer.cc
index ec86526033..abdf577209 100644
--- a/deps/v8/src/regexp/regexp-macro-assembler-tracer.cc
+++ b/deps/v8/src/regexp/regexp-macro-assembler-tracer.cc
@@ -12,9 +12,9 @@ namespace internal {
RegExpMacroAssemblerTracer::RegExpMacroAssemblerTracer(
Isolate* isolate, RegExpMacroAssembler* assembler)
: RegExpMacroAssembler(isolate, assembler->zone()), assembler_(assembler) {
- unsigned int type = assembler->Implementation();
- DCHECK(type < 8);
- const char* impl_names[] = {"IA32", "ARM", "ARM64", "MIPS",
+ IrregexpImplementation type = assembler->Implementation();
+ DCHECK_LT(type, 9);
+ const char* impl_names[] = {"IA32", "ARM", "ARM64", "MIPS", "S390",
"PPC", "X64", "X87", "Bytecode"};
PrintF("RegExpMacroAssembler%s();\n", impl_names[type]);
}
diff --git a/deps/v8/src/regexp/regexp-parser.cc b/deps/v8/src/regexp/regexp-parser.cc
index dba81ae9a7..fd3123f674 100644
--- a/deps/v8/src/regexp/regexp-parser.cc
+++ b/deps/v8/src/regexp/regexp-parser.cc
@@ -1607,7 +1607,7 @@ void RegExpBuilder::AddCharacter(uc16 c) {
void RegExpBuilder::AddUnicodeCharacter(uc32 c) {
- if (c > unibrow::Utf16::kMaxNonSurrogateCharCode) {
+ if (c > static_cast<uc32>(unibrow::Utf16::kMaxNonSurrogateCharCode)) {
DCHECK(unicode());
AddLeadSurrogate(unibrow::Utf16::LeadSurrogate(c));
AddTrailSurrogate(unibrow::Utf16::TrailSurrogate(c));
diff --git a/deps/v8/src/regexp/regexp-utils.cc b/deps/v8/src/regexp/regexp-utils.cc
new file mode 100644
index 0000000000..62daf3f1d5
--- /dev/null
+++ b/deps/v8/src/regexp/regexp-utils.cc
@@ -0,0 +1,192 @@
+// Copyright 2016 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/regexp/regexp-utils.h"
+
+#include "src/factory.h"
+#include "src/isolate.h"
+#include "src/objects-inl.h"
+#include "src/regexp/jsregexp.h"
+
+namespace v8 {
+namespace internal {
+
+Handle<String> RegExpUtils::GenericCaptureGetter(
+ Isolate* isolate, Handle<RegExpMatchInfo> match_info, int capture,
+ bool* ok) {
+ const int index = capture * 2;
+ if (index >= match_info->NumberOfCaptureRegisters()) {
+ if (ok != nullptr) *ok = false;
+ return isolate->factory()->empty_string();
+ }
+
+ const int match_start = match_info->Capture(index);
+ const int match_end = match_info->Capture(index + 1);
+ if (match_start == -1 || match_end == -1) {
+ if (ok != nullptr) *ok = false;
+ return isolate->factory()->empty_string();
+ }
+
+ if (ok != nullptr) *ok = true;
+ Handle<String> last_subject(match_info->LastSubject());
+ return isolate->factory()->NewSubString(last_subject, match_start, match_end);
+}
+
+namespace {
+
+V8_INLINE bool HasInitialRegExpMap(Isolate* isolate, Handle<JSReceiver> recv) {
+ return recv->map() == isolate->regexp_function()->initial_map();
+}
+
+} // namespace
+
+MaybeHandle<Object> RegExpUtils::SetLastIndex(Isolate* isolate,
+ Handle<JSReceiver> recv,
+ int value) {
+ if (HasInitialRegExpMap(isolate, recv)) {
+ JSRegExp::cast(*recv)->SetLastIndex(value);
+ return recv;
+ } else {
+ return Object::SetProperty(recv, isolate->factory()->lastIndex_string(),
+ handle(Smi::FromInt(value), isolate), STRICT);
+ }
+}
+
+MaybeHandle<Object> RegExpUtils::GetLastIndex(Isolate* isolate,
+ Handle<JSReceiver> recv) {
+ if (HasInitialRegExpMap(isolate, recv)) {
+ return handle(JSRegExp::cast(*recv)->LastIndex(), isolate);
+ } else {
+ return Object::GetProperty(recv, isolate->factory()->lastIndex_string());
+ }
+}
+
+// ES#sec-regexpexec Runtime Semantics: RegExpExec ( R, S )
+// Also takes an optional exec method in case our caller
+// has already fetched exec.
+MaybeHandle<Object> RegExpUtils::RegExpExec(Isolate* isolate,
+ Handle<JSReceiver> regexp,
+ Handle<String> string,
+ Handle<Object> exec) {
+ if (exec->IsUndefined(isolate)) {
+ ASSIGN_RETURN_ON_EXCEPTION(
+ isolate, exec,
+ Object::GetProperty(regexp, isolate->factory()->exec_string()), Object);
+ }
+
+ if (exec->IsCallable()) {
+ const int argc = 1;
+ ScopedVector<Handle<Object>> argv(argc);
+ argv[0] = string;
+
+ Handle<Object> result;
+ ASSIGN_RETURN_ON_EXCEPTION(
+ isolate, result,
+ Execution::Call(isolate, exec, regexp, argc, argv.start()), Object);
+
+ if (!result->IsJSReceiver() && !result->IsNull(isolate)) {
+ THROW_NEW_ERROR(isolate,
+ NewTypeError(MessageTemplate::kInvalidRegExpExecResult),
+ Object);
+ }
+ return result;
+ }
+
+ if (!regexp->IsJSRegExp()) {
+ THROW_NEW_ERROR(isolate,
+ NewTypeError(MessageTemplate::kIncompatibleMethodReceiver,
+ isolate->factory()->NewStringFromAsciiChecked(
+ "RegExp.prototype.exec"),
+ regexp),
+ Object);
+ }
+
+ {
+ Handle<JSFunction> regexp_exec = isolate->regexp_exec_function();
+
+ const int argc = 1;
+ ScopedVector<Handle<Object>> argv(argc);
+ argv[0] = string;
+
+ return Execution::Call(isolate, regexp_exec, regexp, argc, argv.start());
+ }
+}
+
+Maybe<bool> RegExpUtils::IsRegExp(Isolate* isolate, Handle<Object> object) {
+ if (!object->IsJSReceiver()) return Just(false);
+
+ Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(object);
+
+ if (isolate->regexp_function()->initial_map() == receiver->map()) {
+ // Fast-path for unmodified JSRegExp instances.
+ // TODO(ishell): Adapt for new fast-path logic.
+ return Just(true);
+ }
+
+ Handle<Object> match;
+ ASSIGN_RETURN_ON_EXCEPTION_VALUE(
+ isolate, match,
+ JSObject::GetProperty(receiver, isolate->factory()->match_symbol()),
+ Nothing<bool>());
+
+ if (!match->IsUndefined(isolate)) return Just(match->BooleanValue());
+ return Just(object->IsJSRegExp());
+}
+
+bool RegExpUtils::IsUnmodifiedRegExp(Isolate* isolate, Handle<Object> obj) {
+ // TODO(ishell): Update this check once map changes for constant field
+ // tracking are landing.
+
+ if (!obj->IsJSReceiver()) return false;
+
+ JSReceiver* recv = JSReceiver::cast(*obj);
+
+ // Check the receiver's map.
+ Handle<JSFunction> regexp_function = isolate->regexp_function();
+ if (recv->map() != regexp_function->initial_map()) return false;
+
+ // Check the receiver's prototype's map.
+ Object* proto = recv->map()->prototype();
+ if (!proto->IsJSReceiver()) return false;
+
+ Handle<Map> initial_proto_initial_map = isolate->regexp_prototype_map();
+ return (JSReceiver::cast(proto)->map() == *initial_proto_initial_map);
+}
+
+int RegExpUtils::AdvanceStringIndex(Isolate* isolate, Handle<String> string,
+ int index, bool unicode) {
+ if (unicode && index < string->length()) {
+ const uint16_t first = string->Get(index);
+ if (first >= 0xD800 && first <= 0xDBFF && string->length() > index + 1) {
+ const uint16_t second = string->Get(index + 1);
+ if (second >= 0xDC00 && second <= 0xDFFF) {
+ return index + 2;
+ }
+ }
+ }
+
+ return index + 1;
+}
+
+MaybeHandle<Object> RegExpUtils::SetAdvancedStringIndex(
+ Isolate* isolate, Handle<JSReceiver> regexp, Handle<String> string,
+ bool unicode) {
+ Handle<Object> last_index_obj;
+ ASSIGN_RETURN_ON_EXCEPTION(
+ isolate, last_index_obj,
+ Object::GetProperty(regexp, isolate->factory()->lastIndex_string()),
+ Object);
+
+ ASSIGN_RETURN_ON_EXCEPTION(isolate, last_index_obj,
+ Object::ToLength(isolate, last_index_obj), Object);
+
+ const int last_index = Handle<Smi>::cast(last_index_obj)->value();
+ const int new_last_index =
+ AdvanceStringIndex(isolate, string, last_index, unicode);
+
+ return SetLastIndex(isolate, regexp, new_last_index);
+}
+
+} // namespace internal
+} // namespace v8
diff --git a/deps/v8/src/regexp/regexp-utils.h b/deps/v8/src/regexp/regexp-utils.h
new file mode 100644
index 0000000000..eff1ed739c
--- /dev/null
+++ b/deps/v8/src/regexp/regexp-utils.h
@@ -0,0 +1,52 @@
+// Copyright 2016 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.
+
+#ifndef V8_REGEXP_REGEXP_UTILS_H_
+#define V8_REGEXP_REGEXP_UTILS_H_
+
+#include "src/objects.h"
+
+namespace v8 {
+namespace internal {
+
+// Helper methods for C++ regexp builtins.
+class RegExpUtils : public AllStatic {
+ public:
+ // Last match info accessors.
+ static Handle<String> GenericCaptureGetter(Isolate* isolate,
+ Handle<RegExpMatchInfo> match_info,
+ int capture, bool* ok = nullptr);
+
+ // Last index (RegExp.lastIndex) accessors.
+ static MUST_USE_RESULT MaybeHandle<Object> SetLastIndex(
+ Isolate* isolate, Handle<JSReceiver> regexp, int value);
+ static MUST_USE_RESULT MaybeHandle<Object> GetLastIndex(
+ Isolate* isolate, Handle<JSReceiver> recv);
+
+ // ES#sec-regexpexec Runtime Semantics: RegExpExec ( R, S )
+ static MUST_USE_RESULT MaybeHandle<Object> RegExpExec(
+ Isolate* isolate, Handle<JSReceiver> regexp, Handle<String> string,
+ Handle<Object> exec);
+
+ // ES#sec-isregexp IsRegExp ( argument )
+ // Includes checking of the match property.
+ static Maybe<bool> IsRegExp(Isolate* isolate, Handle<Object> object);
+
+ // Checks whether the given object is an unmodified JSRegExp instance.
+ // Neither the object's map, nor its prototype's map may be modified.
+ static bool IsUnmodifiedRegExp(Isolate* isolate, Handle<Object> obj);
+
+ // ES#sec-advancestringindex
+ // AdvanceStringIndex ( S, index, unicode )
+ static int AdvanceStringIndex(Isolate* isolate, Handle<String> string,
+ int index, bool unicode);
+ static MUST_USE_RESULT MaybeHandle<Object> SetAdvancedStringIndex(
+ Isolate* isolate, Handle<JSReceiver> regexp, Handle<String> string,
+ bool unicode);
+};
+
+} // namespace internal
+} // namespace v8
+
+#endif // V8_REGEXP_REGEXP_UTILS_H_