Commit e80c0b35 by Abseil Team Committed by vslashg

Export of internal Abseil changes

--
d85f04af95a6fdafb102f7dc393d78d4431b47e5 by Abseil Team <absl-team@google.com>:

Internal change for cord ring

PiperOrigin-RevId: 344541196

--
1ff57908e31a09ec0c98d8316da1263092cc3a1c by Abseil Team <absl-team@google.com>:

Fix typo in comment.

PiperOrigin-RevId: 344214280
GitOrigin-RevId: d85f04af95a6fdafb102f7dc393d78d4431b47e5
Change-Id: I58b3c28f62a5d10dd665b17d58a121f371e1260a
parent 5d8fc919
...@@ -193,6 +193,7 @@ set(ABSL_INTERNAL_DLL_FILES ...@@ -193,6 +193,7 @@ set(ABSL_INTERNAL_DLL_FILES
"strings/escaping.cc" "strings/escaping.cc"
"strings/escaping.h" "strings/escaping.h"
"strings/internal/cord_internal.h" "strings/internal/cord_internal.h"
"strings/internal/cord_rep_flat.h"
"strings/internal/charconv_bigint.cc" "strings/internal/charconv_bigint.cc"
"strings/internal/charconv_bigint.h" "strings/internal/charconv_bigint.h"
"strings/internal/charconv_parse.cc" "strings/internal/charconv_parse.cc"
......
...@@ -24,7 +24,7 @@ ABSL_NAMESPACE_BEGIN ...@@ -24,7 +24,7 @@ ABSL_NAMESPACE_BEGIN
namespace flags_internal { namespace flags_internal {
// An alias for flag fast type id. This value identifies the flag value type // An alias for flag fast type id. This value identifies the flag value type
// simialarly to typeid(T), without relying on RTTI being available. In most // similarly to typeid(T), without relying on RTTI being available. In most
// cases this id is enough to uniquely identify the flag's value type. In a few // cases this id is enough to uniquely identify the flag's value type. In a few
// cases we'll have to resort to using actual RTTI implementation if it is // cases we'll have to resort to using actual RTTI implementation if it is
// available. // available.
......
...@@ -267,7 +267,10 @@ cc_test( ...@@ -267,7 +267,10 @@ cc_test(
cc_library( cc_library(
name = "cord_internal", name = "cord_internal",
hdrs = ["internal/cord_internal.h"], hdrs = [
"internal/cord_internal.h",
"internal/cord_rep_flat.h",
],
copts = ABSL_DEFAULT_COPTS, copts = ABSL_DEFAULT_COPTS,
visibility = ["//visibility:private"], visibility = ["//visibility:private"],
deps = [ deps = [
......
...@@ -557,6 +557,7 @@ absl_cc_library( ...@@ -557,6 +557,7 @@ absl_cc_library(
SRCS SRCS
"cord.cc" "cord.cc"
"internal/cord_internal.h" "internal/cord_internal.h"
"internal/cord_rep_flat.h"
COPTS COPTS
${ABSL_DEFAULT_COPTS} ${ABSL_DEFAULT_COPTS}
DEPS DEPS
......
...@@ -108,8 +108,9 @@ class Refcount { ...@@ -108,8 +108,9 @@ class Refcount {
// functions in the base class. // functions in the base class.
struct CordRepConcat; struct CordRepConcat;
struct CordRepSubstring;
struct CordRepExternal; struct CordRepExternal;
struct CordRepFlat;
struct CordRepSubstring;
// Various representations that we allow // Various representations that we allow
enum CordRepKind { enum CordRepKind {
...@@ -180,6 +181,10 @@ struct CordRepExternal : public CordRep { ...@@ -180,6 +181,10 @@ struct CordRepExternal : public CordRep {
const char* base; const char* base;
// Pointer to function that knows how to call and destroy the releaser. // Pointer to function that knows how to call and destroy the releaser.
ExternalReleaserInvoker releaser_invoker; ExternalReleaserInvoker releaser_invoker;
// Deletes (releases) the external rep.
// Requires rep != nullptr and rep->tag == EXTERNAL
static void Delete(CordRep* rep);
}; };
struct Rank1 {}; struct Rank1 {};
...@@ -220,6 +225,13 @@ struct CordRepExternalImpl ...@@ -220,6 +225,13 @@ struct CordRepExternalImpl
} }
}; };
inline void CordRepExternal::Delete(CordRep* rep) {
assert(rep != nullptr && rep->tag == EXTERNAL);
auto* rep_external = static_cast<CordRepExternal*>(rep);
assert(rep_external->releaser_invoker != nullptr);
rep_external->releaser_invoker(rep_external);
}
template <typename Str> template <typename Str>
struct ConstInitExternalStorage { struct ConstInitExternalStorage {
ABSL_CONST_INIT static CordRepExternal value; ABSL_CONST_INIT static CordRepExternal value;
......
// Copyright 2020 The Abseil Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef ABSL_STRINGS_INTERNAL_CORD_REP_FLAT_H_
#define ABSL_STRINGS_INTERNAL_CORD_REP_FLAT_H_
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <memory>
#include "absl/strings/internal/cord_internal.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace cord_internal {
// Note: all constants below are never ODR used and internal to cord, we define
// these as static constexpr to avoid 'in struct' definition and usage clutter.
// Largest and smallest flat node lengths we are willing to allocate
// Flat allocation size is stored in tag, which currently can encode sizes up
// to 4K, encoded as multiple of either 8 or 32 bytes.
// If we allow for larger sizes, we need to change this to 8/64, 16/128, etc.
// kMinFlatSize is bounded by tag needing to be at least FLAT * 8 bytes, and
// ideally a 'nice' size aligning with allocation and cacheline sizes like 32.
// kMaxFlatSize is bounded by the size resulting in a computed tag no greater
// than MAX_FLAT_TAG. MAX_FLAT_TAG provides for additional 'high' tag values.
static constexpr size_t kFlatOverhead = offsetof(CordRep, data);
static constexpr size_t kMinFlatSize = 32;
static constexpr size_t kMaxFlatSize = 4096;
static constexpr size_t kMaxFlatLength = kMaxFlatSize - kFlatOverhead;
static constexpr size_t kMinFlatLength = kMinFlatSize - kFlatOverhead;
static constexpr size_t AllocatedSizeToTagUnchecked(size_t size) {
return (size <= 1024) ? size / 8 : 128 + size / 32 - 1024 / 32;
}
static_assert(kMinFlatSize / 8 >= FLAT, "");
static_assert(AllocatedSizeToTagUnchecked(kMaxFlatSize) <= MAX_FLAT_TAG, "");
// Helper functions for rounded div, and rounding to exact sizes.
static size_t DivUp(size_t n, size_t m) { return (n + m - 1) / m; }
static size_t RoundUp(size_t n, size_t m) { return DivUp(n, m) * m; }
// Returns the size to the nearest equal or larger value that can be
// expressed exactly as a tag value.
static size_t RoundUpForTag(size_t size) {
return RoundUp(size, (size <= 1024) ? 8 : 32);
}
// Converts the allocated size to a tag, rounding down if the size
// does not exactly match a 'tag expressible' size value. The result is
// undefined if the size exceeds the maximum size that can be encoded in
// a tag, i.e., if size is larger than TagToAllocatedSize(<max tag>).
static uint8_t AllocatedSizeToTag(size_t size) {
const size_t tag = AllocatedSizeToTagUnchecked(size);
assert(tag <= MAX_FLAT_TAG);
return tag;
}
// Converts the provided tag to the corresponding allocated size
static constexpr size_t TagToAllocatedSize(uint8_t tag) {
return (tag <= 128) ? (tag * 8) : (1024 + (tag - 128) * 32);
}
// Converts the provided tag to the corresponding available data length
static constexpr size_t TagToLength(uint8_t tag) {
return TagToAllocatedSize(tag) - kFlatOverhead;
}
// Enforce that kMaxFlatSize maps to a well-known exact tag value.
static_assert(TagToAllocatedSize(224) == kMaxFlatSize, "Bad tag logic");
struct CordRepFlat : public CordRep {
// Creates a new flat node.
static CordRepFlat* New(size_t len) {
if (len <= kMinFlatLength) {
len = kMinFlatLength;
} else if (len > kMaxFlatLength) {
len = kMaxFlatLength;
}
// Round size up so it matches a size we can exactly express in a tag.
const size_t size = RoundUpForTag(len + kFlatOverhead);
void* const raw_rep = ::operator new(size);
CordRepFlat* rep = new (raw_rep) CordRepFlat();
rep->tag = AllocatedSizeToTag(size);
return rep;
}
// Deletes a CordRepFlat instance created previously through a call to New().
// Flat CordReps are allocated and constructed with raw ::operator new and
// placement new, and must be destructed and deallocated accordingly.
static void Delete(CordRep*rep) {
assert(rep->tag >= FLAT);
#if defined(__cpp_sized_deallocation)
size_t size = TagToAllocatedSize(rep->tag);
rep->~CordRep();
::operator delete(rep, size);
#else
rep->~CordRep();
::operator delete(rep);
#endif
}
// Returns the maximum capacity (payload size) of this instance.
size_t Capacity() const { return TagToLength(tag); }
// Returns the allocated size (payload + overhead) of this instance.
size_t AllocatedSize() const { return TagToAllocatedSize(tag); }
};
} // namespace cord_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_INTERNAL_CORD_REP_FLAT_H_
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment