1// Copyright 2019 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "src/parsing/literal-buffer.h"
6
7#include "src/base/strings.h"
8#include "src/execution/isolate.h"
9#include "src/execution/local-isolate.h"
10#include "src/heap/factory.h"
11#include "src/utils/memcopy.h"
12
13namespace v8 {
14namespace internal {
15
16template <typename IsolateT>
17Handle<String> LiteralBuffer::Internalize(IsolateT* isolate) const {
18  if (is_one_byte()) {
19    return isolate->factory()->InternalizeString(one_byte_literal());
20  }
21  return isolate->factory()->InternalizeString(two_byte_literal());
22}
23
24template Handle<String> LiteralBuffer::Internalize(Isolate* isolate) const;
25template Handle<String> LiteralBuffer::Internalize(LocalIsolate* isolate) const;
26
27int LiteralBuffer::NewCapacity(int min_capacity) {
28  return min_capacity < (kMaxGrowth / (kGrowthFactor - 1))
29             ? min_capacity * kGrowthFactor
30             : min_capacity + kMaxGrowth;
31}
32
33void LiteralBuffer::ExpandBuffer() {
34  int min_capacity = std::max({kInitialCapacity, backing_store_.length()});
35  base::Vector<byte> new_store =
36      base::Vector<byte>::New(NewCapacity(min_capacity));
37  if (position_ > 0) {
38    MemCopy(new_store.begin(), backing_store_.begin(), position_);
39  }
40  backing_store_.Dispose();
41  backing_store_ = new_store;
42}
43
44void LiteralBuffer::ConvertToTwoByte() {
45  DCHECK(is_one_byte());
46  base::Vector<byte> new_store;
47  int new_content_size = position_ * base::kUC16Size;
48  if (new_content_size >= backing_store_.length()) {
49    // Ensure room for all currently read code units as UC16 as well
50    // as the code unit about to be stored.
51    new_store = base::Vector<byte>::New(NewCapacity(new_content_size));
52  } else {
53    new_store = backing_store_;
54  }
55  uint8_t* src = backing_store_.begin();
56  uint16_t* dst = reinterpret_cast<uint16_t*>(new_store.begin());
57  for (int i = position_ - 1; i >= 0; i--) {
58    dst[i] = src[i];
59  }
60  if (new_store.begin() != backing_store_.begin()) {
61    backing_store_.Dispose();
62    backing_store_ = new_store;
63  }
64  position_ = new_content_size;
65  is_one_byte_ = false;
66}
67
68void LiteralBuffer::AddTwoByteChar(base::uc32 code_unit) {
69  DCHECK(!is_one_byte());
70  if (position_ >= backing_store_.length()) ExpandBuffer();
71  if (code_unit <=
72      static_cast<base::uc32>(unibrow::Utf16::kMaxNonSurrogateCharCode)) {
73    *reinterpret_cast<uint16_t*>(&backing_store_[position_]) = code_unit;
74    position_ += base::kUC16Size;
75  } else {
76    *reinterpret_cast<uint16_t*>(&backing_store_[position_]) =
77        unibrow::Utf16::LeadSurrogate(code_unit);
78    position_ += base::kUC16Size;
79    if (position_ >= backing_store_.length()) ExpandBuffer();
80    *reinterpret_cast<uint16_t*>(&backing_store_[position_]) =
81        unibrow::Utf16::TrailSurrogate(code_unit);
82    position_ += base::kUC16Size;
83  }
84}
85
86}  // namespace internal
87}  // namespace v8
88