summaryrefslogtreecommitdiff
path: root/deps/v8/src/objects/string.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/objects/string.cc')
-rw-r--r--deps/v8/src/objects/string.cc77
1 files changed, 52 insertions, 25 deletions
diff --git a/deps/v8/src/objects/string.cc b/deps/v8/src/objects/string.cc
index 7af83a5175..4b18ee3d05 100644
--- a/deps/v8/src/objects/string.cc
+++ b/deps/v8/src/objects/string.cc
@@ -10,6 +10,8 @@
#include "src/execution/thread-id.h"
#include "src/handles/handles-inl.h"
#include "src/heap/heap-inl.h"
+#include "src/heap/local-factory-inl.h"
+#include "src/heap/local-heap-inl.h"
#include "src/heap/memory-chunk.h"
#include "src/heap/read-only-heap.h"
#include "src/numbers/conversions.h"
@@ -93,26 +95,32 @@ void MigrateExternalStringResource(Isolate* isolate, ExternalString from,
}
}
+void MigrateExternalString(Isolate* isolate, String string,
+ String internalized) {
+ if (internalized.IsExternalOneByteString()) {
+ MigrateExternalStringResource(isolate, ExternalString::cast(string),
+ ExternalOneByteString::cast(internalized));
+ } else if (internalized.IsExternalTwoByteString()) {
+ MigrateExternalStringResource(isolate, ExternalString::cast(string),
+ ExternalTwoByteString::cast(internalized));
+ } else {
+ // If the external string is duped into an existing non-external
+ // internalized string, free its resource (it's about to be rewritten
+ // into a ThinString below).
+ isolate->heap()->FinalizeExternalString(string);
+ }
+}
+
} // namespace
-void String::MakeThin(Isolate* isolate, String internalized) {
+template <typename IsolateT>
+void String::MakeThin(IsolateT* isolate, String internalized) {
DisallowGarbageCollection no_gc;
DCHECK_NE(*this, internalized);
DCHECK(internalized.IsInternalizedString());
if (this->IsExternalString()) {
- if (internalized.IsExternalOneByteString()) {
- MigrateExternalStringResource(isolate, ExternalString::cast(*this),
- ExternalOneByteString::cast(internalized));
- } else if (internalized.IsExternalTwoByteString()) {
- MigrateExternalStringResource(isolate, ExternalString::cast(*this),
- ExternalTwoByteString::cast(internalized));
- } else {
- // If the external string is duped into an existing non-external
- // internalized string, free its resource (it's about to be rewritten
- // into a ThinString below).
- isolate->heap()->FinalizeExternalString(*this);
- }
+ MigrateExternalString(isolate->AsIsolate(), *this, internalized);
}
bool has_pointers = StringShape(*this).IsIndirect();
@@ -131,9 +139,8 @@ void String::MakeThin(Isolate* isolate, String internalized) {
Address thin_end = thin.address() + ThinString::kSize;
int size_delta = old_size - ThinString::kSize;
if (size_delta != 0) {
- Heap* heap = isolate->heap();
- if (!heap->IsLargeObject(thin)) {
- heap->CreateFillerObjectAt(
+ if (!Heap::IsLargeObject(thin)) {
+ isolate->heap()->CreateFillerObjectAt(
thin_end, size_delta,
has_pointers ? ClearRecordedSlots::kYes : ClearRecordedSlots::kNo);
} else {
@@ -144,6 +151,9 @@ void String::MakeThin(Isolate* isolate, String internalized) {
}
}
+template void String::MakeThin(Isolate* isolate, String internalized);
+template void String::MakeThin(LocalIsolate* isolate, String internalized);
+
bool String::MakeExternal(v8::String::ExternalStringResource* resource) {
// Disallow garbage collection to avoid possible GC vs string access deadlock.
DisallowGarbageCollection no_gc;
@@ -633,6 +643,7 @@ std::unique_ptr<char[]> String::ToCString(AllowNullsFlag allow_nulls,
return ToCString(allow_nulls, robust_flag, 0, -1, length_return);
}
+// static
template <typename sinkchar>
void String::WriteToFlat(String source, sinkchar* sink, int from, int to) {
DCHECK(!SharedStringAccessGuardIfNeeded::IsNeeded(source));
@@ -640,6 +651,7 @@ void String::WriteToFlat(String source, sinkchar* sink, int from, int to) {
SharedStringAccessGuardIfNeeded::NotNeeded());
}
+// static
template <typename sinkchar>
void String::WriteToFlat(String source, sinkchar* sink, int from, int to,
const SharedStringAccessGuardIfNeeded& access_guard) {
@@ -794,6 +806,13 @@ template Handle<FixedArray> String::CalculateLineEnds(LocalIsolate* isolate,
bool include_ending_line);
bool String::SlowEquals(String other) const {
+ DCHECK(!SharedStringAccessGuardIfNeeded::IsNeeded(*this));
+ DCHECK(!SharedStringAccessGuardIfNeeded::IsNeeded(other));
+ return SlowEquals(other, SharedStringAccessGuardIfNeeded::NotNeeded());
+}
+
+bool String::SlowEquals(
+ String other, const SharedStringAccessGuardIfNeeded& access_guard) const {
DisallowGarbageCollection no_gc;
// Fast check: negative check with lengths.
int len = length();
@@ -833,16 +852,18 @@ bool String::SlowEquals(String other) const {
// We know the strings are both non-empty. Compare the first chars
// before we try to flatten the strings.
- if (this->Get(0) != other.Get(0)) return false;
+ if (this->Get(0, access_guard) != other.Get(0, access_guard)) return false;
if (IsSeqOneByteString() && other.IsSeqOneByteString()) {
- const uint8_t* str1 = SeqOneByteString::cast(*this).GetChars(no_gc);
- const uint8_t* str2 = SeqOneByteString::cast(other).GetChars(no_gc);
+ const uint8_t* str1 =
+ SeqOneByteString::cast(*this).GetChars(no_gc, access_guard);
+ const uint8_t* str2 =
+ SeqOneByteString::cast(other).GetChars(no_gc, access_guard);
return CompareCharsEqual(str1, str2, len);
}
StringComparator comparator;
- return comparator.Equals(*this, other);
+ return comparator.Equals(*this, other, access_guard);
}
// static
@@ -1326,7 +1347,8 @@ bool String::HasOneBytePrefix(base::Vector<const char> str) {
namespace {
template <typename Char>
-uint32_t HashString(String string, size_t start, int length, uint64_t seed) {
+uint32_t HashString(String string, size_t start, int length, uint64_t seed,
+ const SharedStringAccessGuardIfNeeded& access_guard) {
DisallowGarbageCollection no_gc;
if (length > String::kMaxHashCalcLength) {
@@ -1340,10 +1362,10 @@ uint32_t HashString(String string, size_t start, int length, uint64_t seed) {
DCHECK_EQ(0, start);
DCHECK(!string.IsFlat());
buffer.reset(new Char[length]);
- String::WriteToFlat(string, buffer.get(), 0, length);
+ String::WriteToFlat(string, buffer.get(), 0, length, access_guard);
chars = buffer.get();
} else {
- chars = string.GetChars<Char>(no_gc) + start;
+ chars = string.GetChars<Char>(no_gc, access_guard) + start;
}
return StringHasher::HashSequentialString<Char>(chars, length, seed);
@@ -1352,6 +1374,11 @@ uint32_t HashString(String string, size_t start, int length, uint64_t seed) {
} // namespace
uint32_t String::ComputeAndSetHash() {
+ DCHECK(!SharedStringAccessGuardIfNeeded::IsNeeded(*this));
+ return ComputeAndSetHash(SharedStringAccessGuardIfNeeded::NotNeeded());
+}
+uint32_t String::ComputeAndSetHash(
+ const SharedStringAccessGuardIfNeeded& access_guard) {
DisallowGarbageCollection no_gc;
// Should only be called if hash code has not yet been computed.
DCHECK(!HasHashCode());
@@ -1377,8 +1404,8 @@ uint32_t String::ComputeAndSetHash() {
}
uint32_t raw_hash_field =
string.IsOneByteRepresentation()
- ? HashString<uint8_t>(string, start, length(), seed)
- : HashString<uint16_t>(string, start, length(), seed);
+ ? HashString<uint8_t>(string, start, length(), seed, access_guard)
+ : HashString<uint16_t>(string, start, length(), seed, access_guard);
set_raw_hash_field(raw_hash_field);
// Check the hash code is there.