Upgrade V8 to version 4.9.385.28
https://chromium.googlesource.com/v8/v8/+/4.9.385.28
FPIIM-449
Change-Id: I4b2e74289d4bf3667f2f3dc8aa2e541f63e26eb4
diff --git a/src/runtime/runtime-regexp.cc b/src/runtime/runtime-regexp.cc
index 9296a4b..138b4dc 100644
--- a/src/runtime/runtime-regexp.cc
+++ b/src/runtime/runtime-regexp.cc
@@ -2,12 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "src/v8.h"
+#include "src/runtime/runtime-utils.h"
#include "src/arguments.h"
-#include "src/jsregexp-inl.h"
-#include "src/jsregexp.h"
-#include "src/runtime/runtime-utils.h"
+#include "src/conversions-inl.h"
+#include "src/isolate-inl.h"
+#include "src/messages.h"
+#include "src/regexp/jsregexp-inl.h"
+#include "src/regexp/jsregexp.h"
#include "src/string-builder.h"
#include "src/string-search.h"
@@ -637,8 +639,12 @@
// fresly allocated page or on an already swept page. Hence, the sweeper
// 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);
+ // TODO(hpayer): We should shrink the large object page if the size
+ // of the object changed significantly.
+ if (!heap->lo_space()->Contains(*answer)) {
+ heap->CreateFillerObjectAt(end_of_string, delta);
+ }
+ heap->AdjustLiveBytes(*answer, -delta, Heap::CONCURRENT_TO_SWEEPER);
return *answer;
}
@@ -652,7 +658,7 @@
CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 1);
CONVERT_ARG_HANDLE_CHECKED(JSArray, last_match_info, 3);
- RUNTIME_ASSERT(regexp->GetFlags().is_global());
+ RUNTIME_ASSERT(regexp->GetFlags() & JSRegExp::kGlobal);
RUNTIME_ASSERT(last_match_info->HasFastObjectElements());
subject = String::Flatten(subject);
@@ -687,8 +693,10 @@
RUNTIME_ASSERT(pattern_length > 0);
if (limit == 0xffffffffu) {
+ FixedArray* last_match_cache_unused;
Handle<Object> cached_answer(
RegExpResultsCache::Lookup(isolate->heap(), *subject, *pattern,
+ &last_match_cache_unused,
RegExpResultsCache::STRING_SPLIT_SUBSTRINGS),
isolate);
if (*cached_answer != Smi::FromInt(0)) {
@@ -732,25 +740,26 @@
DCHECK(result->HasFastObjectElements());
- if (part_count == 1 && indices.at(0) == subject_length) {
- FixedArray::cast(result->elements())->set(0, *subject);
- return *result;
- }
-
Handle<FixedArray> elements(FixedArray::cast(result->elements()));
- int part_start = 0;
- for (int i = 0; i < part_count; i++) {
- HandleScope local_loop_handle(isolate);
- int part_end = indices.at(i);
- Handle<String> substring =
- isolate->factory()->NewProperSubString(subject, part_start, part_end);
- elements->set(i, *substring);
- part_start = part_end + pattern_length;
+
+ if (part_count == 1 && indices.at(0) == subject_length) {
+ elements->set(0, *subject);
+ } else {
+ int part_start = 0;
+ for (int i = 0; i < part_count; i++) {
+ HandleScope local_loop_handle(isolate);
+ int part_end = indices.at(i);
+ Handle<String> substring =
+ isolate->factory()->NewProperSubString(subject, part_start, part_end);
+ elements->set(i, *substring);
+ part_start = part_end + pattern_length;
+ }
}
if (limit == 0xffffffffu) {
if (result->HasFastObjectElements()) {
RegExpResultsCache::Enter(isolate, subject, pattern, elements,
+ isolate->factory()->empty_fixed_array(),
RegExpResultsCache::STRING_SPLIT_SUBSTRINGS);
}
}
@@ -759,7 +768,7 @@
}
-RUNTIME_FUNCTION(Runtime_RegExpExecRT) {
+RUNTIME_FUNCTION(Runtime_RegExpExec) {
HandleScope scope(isolate);
DCHECK(args.length() == 4);
CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 0);
@@ -779,6 +788,22 @@
}
+RUNTIME_FUNCTION(Runtime_RegExpFlags) {
+ SealHandleScope shs(isolate);
+ DCHECK(args.length() == 1);
+ CONVERT_ARG_CHECKED(JSRegExp, regexp, 0);
+ return regexp->flags();
+}
+
+
+RUNTIME_FUNCTION(Runtime_RegExpSource) {
+ SealHandleScope shs(isolate);
+ DCHECK(args.length() == 1);
+ CONVERT_ARG_CHECKED(JSRegExp, regexp, 0);
+ return regexp->source();
+}
+
+
RUNTIME_FUNCTION(Runtime_RegExpConstructResult) {
HandleScope handle_scope(isolate);
DCHECK(args.length() == 3);
@@ -789,7 +814,7 @@
Handle<FixedArray> elements = isolate->factory()->NewFixedArray(size);
Handle<Map> regexp_map(isolate->native_context()->regexp_result_map());
Handle<JSObject> object =
- isolate->factory()->NewJSObjectFromMap(regexp_map, NOT_TENURED, false);
+ isolate->factory()->NewJSObjectFromMap(regexp_map, NOT_TENURED);
Handle<JSArray> array = Handle<JSArray>::cast(object);
array->set_elements(*elements);
array->set_length(Smi::FromInt(size));
@@ -800,134 +825,16 @@
}
-static JSRegExp::Flags RegExpFlagsFromString(Handle<String> flags,
- bool* success) {
- uint32_t value = JSRegExp::NONE;
- int length = flags->length();
- // A longer flags string cannot be valid.
- if (length > 4) return JSRegExp::Flags(0);
- for (int i = 0; i < length; i++) {
- uint32_t flag = JSRegExp::NONE;
- switch (flags->Get(i)) {
- case 'g':
- flag = JSRegExp::GLOBAL;
- break;
- case 'i':
- flag = JSRegExp::IGNORE_CASE;
- break;
- case 'm':
- flag = JSRegExp::MULTILINE;
- break;
- case 'y':
- if (!FLAG_harmony_regexps) return JSRegExp::Flags(0);
- flag = JSRegExp::STICKY;
- break;
- default:
- return JSRegExp::Flags(0);
- }
- // Duplicate flag.
- if (value & flag) return JSRegExp::Flags(0);
- value |= flag;
- }
- *success = true;
- return JSRegExp::Flags(value);
-}
-
-
RUNTIME_FUNCTION(Runtime_RegExpInitializeAndCompile) {
HandleScope scope(isolate);
DCHECK(args.length() == 3);
CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 0);
CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
- CONVERT_ARG_HANDLE_CHECKED(String, flags_string, 2);
- Factory* factory = isolate->factory();
- // If source is the empty string we set it to "(?:)" instead as
- // suggested by ECMA-262, 5th, section 15.10.4.1.
- if (source->length() == 0) source = factory->query_colon_string();
+ CONVERT_ARG_HANDLE_CHECKED(String, flags, 2);
- bool success = false;
- JSRegExp::Flags flags = RegExpFlagsFromString(flags_string, &success);
- if (!success) {
- Handle<FixedArray> element = factory->NewFixedArray(1);
- element->set(0, *flags_string);
- Handle<JSArray> args = factory->NewJSArrayWithElements(element);
- THROW_NEW_ERROR_RETURN_FAILURE(
- isolate, NewSyntaxError("invalid_regexp_flags", args));
- }
+ RETURN_FAILURE_ON_EXCEPTION(isolate,
+ JSRegExp::Initialize(regexp, source, flags));
- 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());
- Handle<Object> sticky = factory->ToBoolean(flags.is_sticky());
-
- Map* map = regexp->map();
- Object* constructor = map->constructor();
- if (!FLAG_harmony_regexps && constructor->IsJSFunction() &&
- JSFunction::cast(constructor)->initial_map() == map) {
- // If we still have the original map, set in-object properties directly.
- // Both true and false are immovable immortal objects so no need for write
- // barrier.
- regexp->InObjectPropertyAtPut(JSRegExp::kGlobalFieldIndex, *global,
- SKIP_WRITE_BARRIER);
- regexp->InObjectPropertyAtPut(JSRegExp::kIgnoreCaseFieldIndex, *ignore_case,
- SKIP_WRITE_BARRIER);
- regexp->InObjectPropertyAtPut(JSRegExp::kMultilineFieldIndex, *multiline,
- SKIP_WRITE_BARRIER);
- regexp->InObjectPropertyAtPut(JSRegExp::kLastIndexFieldIndex,
- Smi::FromInt(0), SKIP_WRITE_BARRIER);
- } else {
- // Map has changed, so use generic, but slower, method. We also end here if
- // the --harmony-regexp flag is set, because the initial map does not have
- // space for the 'sticky' flag, since it is from the snapshot, but must work
- // both with and without --harmony-regexp. When sticky comes out from under
- // the flag, we will be able to use the fast initial map.
- PropertyAttributes final =
- static_cast<PropertyAttributes>(READ_ONLY | DONT_ENUM | DONT_DELETE);
- PropertyAttributes writable =
- static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE);
- Handle<Object> zero(Smi::FromInt(0), isolate);
- JSObject::SetOwnPropertyIgnoreAttributes(regexp, factory->global_string(),
- global, final).Check();
- JSObject::SetOwnPropertyIgnoreAttributes(
- regexp, factory->ignore_case_string(), ignore_case, final).Check();
- JSObject::SetOwnPropertyIgnoreAttributes(
- regexp, factory->multiline_string(), multiline, final).Check();
- if (FLAG_harmony_regexps) {
- JSObject::SetOwnPropertyIgnoreAttributes(regexp, factory->sticky_string(),
- sticky, final).Check();
- }
- JSObject::SetOwnPropertyIgnoreAttributes(
- regexp, factory->last_index_string(), zero, writable).Check();
- }
-
- Handle<Object> result;
- ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
- isolate, result, RegExpImpl::Compile(regexp, source, flags));
- return *result;
-}
-
-
-RUNTIME_FUNCTION(Runtime_MaterializeRegExpLiteral) {
- HandleScope scope(isolate);
- DCHECK(args.length() == 4);
- CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0);
- CONVERT_SMI_ARG_CHECKED(index, 1);
- CONVERT_ARG_HANDLE_CHECKED(String, pattern, 2);
- CONVERT_ARG_HANDLE_CHECKED(String, flags, 3);
-
- // Get the RegExp function from the context in the literals array.
- // This is the RegExp function from the context in which the
- // function was created. We do not use the RegExp function from the
- // current native context because this might be the RegExp function
- // from another context which we should not have access to.
- Handle<JSFunction> constructor = Handle<JSFunction>(
- JSFunction::NativeContextFromLiterals(*literals)->regexp_function());
- // Compute the regular expression literal.
- Handle<Object> regexp;
- ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
- isolate, regexp,
- RegExpImpl::CreateRegExpLiteral(constructor, pattern, flags));
- literals->set(index, *regexp);
return *regexp;
}
@@ -948,23 +855,23 @@
static const int kMinLengthToCache = 0x1000;
if (subject_length > kMinLengthToCache) {
- Handle<Object> cached_answer(
- RegExpResultsCache::Lookup(isolate->heap(), *subject, regexp->data(),
- RegExpResultsCache::REGEXP_MULTIPLE_INDICES),
- isolate);
- if (*cached_answer != Smi::FromInt(0)) {
+ FixedArray* last_match_cache;
+ Object* cached_answer = RegExpResultsCache::Lookup(
+ isolate->heap(), *subject, regexp->data(), &last_match_cache,
+ RegExpResultsCache::REGEXP_MULTIPLE_INDICES);
+ if (cached_answer->IsFixedArray()) {
+ int capture_registers = (capture_count + 1) * 2;
+ int32_t* last_match = NewArray<int32_t>(capture_registers);
+ for (int i = 0; i < capture_registers; i++) {
+ last_match[i] = Smi::cast(last_match_cache->get(i))->value();
+ }
Handle<FixedArray> cached_fixed_array =
- Handle<FixedArray>(FixedArray::cast(*cached_answer));
+ Handle<FixedArray>(FixedArray::cast(cached_answer));
// The cache FixedArray is a COW-array and can therefore be reused.
JSArray::SetContent(result_array, cached_fixed_array);
- // The actual length of the result array is stored in the last element of
- // the backing store (the backing FixedArray may have a larger capacity).
- Object* cached_fixed_array_last_element =
- cached_fixed_array->get(cached_fixed_array->length() - 1);
- Smi* js_array_length = Smi::cast(cached_fixed_array_last_element);
- result_array->set_length(js_array_length);
RegExpImpl::SetLastMatchInfo(last_match_array, subject, capture_count,
- NULL);
+ last_match);
+ DeleteArray(last_match);
return *result_array;
}
}
@@ -1052,19 +959,24 @@
}
RegExpImpl::SetLastMatchInfo(last_match_array, subject, capture_count,
- NULL);
+ global_cache.LastSuccessfulMatch());
if (subject_length > kMinLengthToCache) {
- // Store the length of the result array into the last element of the
- // backing FixedArray.
- builder.EnsureCapacity(1);
- Handle<FixedArray> fixed_array = builder.array();
- fixed_array->set(fixed_array->length() - 1,
- Smi::FromInt(builder.length()));
+ // Store the last successful match into the array for caching.
+ // TODO(yangguo): do not expose last match to JS and simplify caching.
+ int capture_registers = (capture_count + 1) * 2;
+ Handle<FixedArray> last_match_cache =
+ isolate->factory()->NewFixedArray(capture_registers);
+ int32_t* last_match = global_cache.LastSuccessfulMatch();
+ for (int i = 0; i < capture_registers; i++) {
+ last_match_cache->set(i, Smi::FromInt(last_match[i]));
+ }
+ Handle<FixedArray> result_fixed_array = builder.array();
+ result_fixed_array->Shrink(builder.length());
// Cache the result and turn the FixedArray into a COW array.
- RegExpResultsCache::Enter(isolate, subject,
- handle(regexp->data(), isolate), fixed_array,
- RegExpResultsCache::REGEXP_MULTIPLE_INDICES);
+ RegExpResultsCache::Enter(
+ isolate, subject, handle(regexp->data(), isolate), result_fixed_array,
+ last_match_cache, RegExpResultsCache::REGEXP_MULTIPLE_INDICES);
}
return *builder.ToJSArray(result_array);
} else {
@@ -1080,15 +992,15 @@
HandleScope handles(isolate);
DCHECK(args.length() == 4);
- CONVERT_ARG_HANDLE_CHECKED(String, subject, 1);
CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 0);
+ CONVERT_ARG_HANDLE_CHECKED(String, subject, 1);
CONVERT_ARG_HANDLE_CHECKED(JSArray, last_match_info, 2);
CONVERT_ARG_HANDLE_CHECKED(JSArray, result_array, 3);
RUNTIME_ASSERT(last_match_info->HasFastObjectElements());
RUNTIME_ASSERT(result_array->HasFastObjectElements());
subject = String::Flatten(subject);
- RUNTIME_ASSERT(regexp->GetFlags().is_global());
+ RUNTIME_ASSERT(regexp->GetFlags() & JSRegExp::kGlobal);
if (regexp->CaptureCount() == 0) {
return SearchRegExpMultiple<false>(isolate, subject, regexp,
@@ -1100,23 +1012,20 @@
}
-RUNTIME_FUNCTION(RuntimeReference_RegExpConstructResult) {
+RUNTIME_FUNCTION(Runtime_RegExpExecReThrow) {
SealHandleScope shs(isolate);
- return __RT_impl_Runtime_RegExpConstructResult(args, isolate);
+ DCHECK(args.length() == 4);
+ Object* exception = isolate->pending_exception();
+ isolate->clear_pending_exception();
+ return isolate->ReThrow(exception);
}
-RUNTIME_FUNCTION(RuntimeReference_RegExpExec) {
- SealHandleScope shs(isolate);
- return __RT_impl_Runtime_RegExpExecRT(args, isolate);
-}
-
-
-RUNTIME_FUNCTION(RuntimeReference_IsRegExp) {
+RUNTIME_FUNCTION(Runtime_IsRegExp) {
SealHandleScope shs(isolate);
DCHECK(args.length() == 1);
CONVERT_ARG_CHECKED(Object, obj, 0);
return isolate->heap()->ToBoolean(obj->IsJSRegExp());
}
-}
-} // namespace v8::internal
+} // namespace internal
+} // namespace v8