| // Copyright 2017 The Chromium 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 THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_STRING_RESOURCE_H_ |
| #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_STRING_RESOURCE_H_ |
| |
| #include "base/macros.h" |
| #include "third_party/blink/renderer/platform/bindings/parkable_string.h" |
| #include "third_party/blink/renderer/platform/platform_export.h" |
| #include "third_party/blink/renderer/platform/wtf/allocator.h" |
| #include "third_party/blink/renderer/platform/wtf/text/atomic_string.h" |
| #include "third_party/blink/renderer/platform/wtf/threading.h" |
| #include "v8/include/v8.h" |
| |
| namespace blink { |
| |
| // StringResource is a helper class for V8ExternalString. It is used |
| // to manage the life-cycle of the underlying buffer of the external string. |
| class StringResourceBase { |
| USING_FAST_MALLOC(StringResourceBase); |
| |
| public: |
| explicit StringResourceBase(const String& string) : plain_string_(string) { |
| #if DCHECK_IS_ON() |
| thread_id_ = WTF::CurrentThread(); |
| #endif |
| DCHECK(!string.IsNull()); |
| v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory( |
| string.CharactersSizeInBytes()); |
| } |
| |
| explicit StringResourceBase(const AtomicString& string) |
| : plain_string_(string.GetString()), atomic_string_(string) { |
| #if DCHECK_IS_ON() |
| thread_id_ = WTF::CurrentThread(); |
| #endif |
| DCHECK(!string.IsNull()); |
| v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory( |
| string.CharactersSizeInBytes()); |
| } |
| |
| explicit StringResourceBase(const ParkableString& string) |
| : parkable_string_(string) { |
| #if DCHECK_IS_ON() |
| thread_id_ = WTF::CurrentThread(); |
| #endif |
| // TODO(lizeb): This is only true without compression. |
| DCHECK(!string.IsNull()); |
| v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory( |
| string.CharactersSizeInBytes()); |
| } |
| |
| virtual ~StringResourceBase() { |
| #if DCHECK_IS_ON() |
| DCHECK(thread_id_ == WTF::CurrentThread()); |
| #endif |
| int64_t reduced_external_memory = plain_string_.CharactersSizeInBytes(); |
| if (plain_string_.Impl() != atomic_string_.Impl() && |
| !atomic_string_.IsNull()) |
| reduced_external_memory += atomic_string_.CharactersSizeInBytes(); |
| v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory( |
| -reduced_external_memory); |
| } |
| |
| String GetWTFString() { |
| if (!parkable_string_.IsNull()) { |
| DCHECK(plain_string_.IsNull()); |
| DCHECK(atomic_string_.IsNull()); |
| return parkable_string_.ToString(); |
| } |
| return plain_string_; |
| } |
| |
| AtomicString GetAtomicString() { |
| #if DCHECK_IS_ON() |
| DCHECK(thread_id_ == WTF::CurrentThread()); |
| #endif |
| if (!parkable_string_.IsNull()) { |
| DCHECK(plain_string_.IsNull()); |
| DCHECK(atomic_string_.IsNull()); |
| return AtomicString(parkable_string_.ToString()); |
| } |
| if (atomic_string_.IsNull()) { |
| atomic_string_ = AtomicString(plain_string_); |
| DCHECK(!atomic_string_.IsNull()); |
| if (plain_string_.Impl() != atomic_string_.Impl()) { |
| v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory( |
| atomic_string_.CharactersSizeInBytes()); |
| } |
| } |
| return atomic_string_; |
| } |
| |
| protected: |
| // A shallow copy of the string. Keeps the string buffer alive until the V8 |
| // engine garbage collects it. |
| String plain_string_; |
| // If this string is atomic or has been made atomic earlier the |
| // atomic string is held here. In the case where the string starts |
| // off non-atomic and becomes atomic later it is necessary to keep |
| // the original string alive because v8 may keep derived pointers |
| // into that string. |
| AtomicString atomic_string_; |
| // If this string is parkable, its value is held here, and the other |
| // members above are null. |
| ParkableString parkable_string_; |
| |
| private: |
| #if DCHECK_IS_ON() |
| WTF::ThreadIdentifier thread_id_; |
| #endif |
| |
| DISALLOW_COPY_AND_ASSIGN(StringResourceBase); |
| }; |
| |
| class StringResource16 final : public StringResourceBase, |
| public v8::String::ExternalStringResource { |
| public: |
| explicit StringResource16(const String& string) : StringResourceBase(string) { |
| DCHECK(!string.Is8Bit()); |
| } |
| |
| explicit StringResource16(const AtomicString& string) |
| : StringResourceBase(string) { |
| DCHECK(!string.Is8Bit()); |
| } |
| |
| size_t length() const override { return plain_string_.Impl()->length(); } |
| const uint16_t* data() const override { |
| return reinterpret_cast<const uint16_t*>( |
| plain_string_.Impl()->Characters16()); |
| } |
| |
| DISALLOW_COPY_AND_ASSIGN(StringResource16); |
| }; |
| |
| class StringResource8 final : public StringResourceBase, |
| public v8::String::ExternalOneByteStringResource { |
| public: |
| explicit StringResource8(const String& string) : StringResourceBase(string) { |
| DCHECK(string.Is8Bit()); |
| } |
| |
| explicit StringResource8(const AtomicString& string) |
| : StringResourceBase(string) { |
| DCHECK(string.Is8Bit()); |
| } |
| |
| size_t length() const override { return plain_string_.Impl()->length(); } |
| const char* data() const override { |
| return reinterpret_cast<const char*>(plain_string_.Impl()->Characters8()); |
| } |
| |
| DISALLOW_COPY_AND_ASSIGN(StringResource8); |
| }; |
| |
| class ParkableStringResource16 final |
| : public StringResourceBase, |
| public v8::String::ExternalStringResource { |
| public: |
| explicit ParkableStringResource16(const ParkableString& string) |
| : StringResourceBase(string) { |
| DCHECK(!parkable_string_.Is8Bit()); |
| } |
| |
| bool IsCacheable() const override { |
| return !parkable_string_.may_be_parked(); |
| } |
| |
| void Lock() const override { parkable_string_.Lock(); } |
| |
| void Unlock() const override { parkable_string_.Unlock(); } |
| |
| size_t length() const override { return parkable_string_.length(); } |
| |
| const uint16_t* data() const override { |
| return reinterpret_cast<const uint16_t*>(parkable_string_.Characters16()); |
| } |
| |
| DISALLOW_COPY_AND_ASSIGN(ParkableStringResource16); |
| }; |
| |
| class ParkableStringResource8 final |
| : public StringResourceBase, |
| public v8::String::ExternalOneByteStringResource { |
| public: |
| explicit ParkableStringResource8(const ParkableString& string) |
| : StringResourceBase(string) { |
| DCHECK(parkable_string_.Is8Bit()); |
| } |
| |
| bool IsCacheable() const override { |
| return !parkable_string_.may_be_parked(); |
| } |
| |
| void Lock() const override { parkable_string_.Lock(); } |
| |
| void Unlock() const override { parkable_string_.Unlock(); } |
| |
| size_t length() const override { return parkable_string_.length(); } |
| |
| const char* data() const override { |
| return reinterpret_cast<const char*>(parkable_string_.Characters8()); |
| } |
| |
| DISALLOW_COPY_AND_ASSIGN(ParkableStringResource8); |
| }; |
| |
| enum ExternalMode { kExternalize, kDoNotExternalize }; |
| |
| template <typename StringType> |
| PLATFORM_EXPORT StringType ToBlinkString(v8::Local<v8::String>, ExternalMode); |
| PLATFORM_EXPORT String ToBlinkString(int value); |
| |
| } // namespace blink |
| |
| #endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_STRING_RESOURCE_H_ |