1 // Copyright 2018 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/codegen/string-constants.h"
6
7 #include "src/base/functional.h"
8 #include "src/numbers/dtoa.h"
9 #include "src/objects/objects.h"
10 #include "src/objects/string-inl.h"
11
12 namespace v8 {
13 namespace internal {
14
AllocateStringConstant(Isolate * isolate) const15 Handle<String> StringConstantBase::AllocateStringConstant(
16 Isolate* isolate) const {
17 if (!flattened_.is_null()) {
18 return flattened_;
19 }
20
21 Handle<String> result;
22 switch (kind()) {
23 case StringConstantKind::kStringLiteral: {
24 result = static_cast<const StringLiteral*>(this)->str();
25 CHECK(!result.is_null());
26 break;
27 }
28 case StringConstantKind::kNumberToStringConstant: {
29 auto num_constant = static_cast<const NumberToStringConstant*>(this);
30 Handle<Object> num_obj =
31 isolate->factory()->NewNumber(num_constant->num());
32 result = isolate->factory()->NumberToString(num_obj);
33 CHECK(!result.is_null());
34 break;
35 }
36 case StringConstantKind::kStringCons: {
37 Handle<String> lhs =
38 static_cast<const StringCons*>(this)->lhs()->AllocateStringConstant(
39 isolate);
40 Handle<String> rhs =
41 static_cast<const StringCons*>(this)->rhs()->AllocateStringConstant(
42 isolate);
43 result = isolate->factory()->NewConsString(lhs, rhs).ToHandleChecked();
44 break;
45 }
46 }
47
48 // TODO(mslekova): Normally we'd want to flatten the string here
49 // but that results in OOM for too long strings.
50 Memoize(result);
51 return flattened_;
52 }
53
operator ==(const StringConstantBase & other) const54 bool StringConstantBase::operator==(const StringConstantBase& other) const {
55 if (kind() != other.kind()) return false;
56
57 switch (kind()) {
58 case StringConstantKind::kStringLiteral: {
59 return static_cast<const StringLiteral*>(this) ==
60 static_cast<const StringLiteral*>(&other);
61 }
62 case StringConstantKind::kNumberToStringConstant: {
63 return static_cast<const NumberToStringConstant*>(this) ==
64 static_cast<const NumberToStringConstant*>(&other);
65 }
66 case StringConstantKind::kStringCons: {
67 return static_cast<const StringCons*>(this) ==
68 static_cast<const StringCons*>(&other);
69 }
70 }
71 UNREACHABLE();
72 }
73
hash_value(StringConstantBase const & base)74 size_t hash_value(StringConstantBase const& base) {
75 switch (base.kind()) {
76 case StringConstantKind::kStringLiteral: {
77 return hash_value(*static_cast<const StringLiteral*>(&base));
78 }
79 case StringConstantKind::kNumberToStringConstant: {
80 return hash_value(*static_cast<const NumberToStringConstant*>(&base));
81 }
82 case StringConstantKind::kStringCons: {
83 return hash_value(*static_cast<const StringCons*>(&base));
84 }
85 }
86 UNREACHABLE();
87 }
88
operator ==(StringLiteral const & lhs,StringLiteral const & rhs)89 bool operator==(StringLiteral const& lhs, StringLiteral const& rhs) {
90 return lhs.str().address() == rhs.str().address();
91 }
92
operator !=(StringLiteral const & lhs,StringLiteral const & rhs)93 bool operator!=(StringLiteral const& lhs, StringLiteral const& rhs) {
94 return !(lhs == rhs);
95 }
96
hash_value(StringLiteral const & p)97 size_t hash_value(StringLiteral const& p) {
98 return base::hash_combine(p.str().address());
99 }
100
operator <<(std::ostream & os,StringLiteral const & p)101 std::ostream& operator<<(std::ostream& os, StringLiteral const& p) {
102 return os << Brief(*p.str());
103 }
104
operator ==(NumberToStringConstant const & lhs,NumberToStringConstant const & rhs)105 bool operator==(NumberToStringConstant const& lhs,
106 NumberToStringConstant const& rhs) {
107 return lhs.num() == rhs.num();
108 }
109
operator !=(NumberToStringConstant const & lhs,NumberToStringConstant const & rhs)110 bool operator!=(NumberToStringConstant const& lhs,
111 NumberToStringConstant const& rhs) {
112 return !(lhs == rhs);
113 }
114
hash_value(NumberToStringConstant const & p)115 size_t hash_value(NumberToStringConstant const& p) {
116 return base::hash_combine(p.num());
117 }
118
operator <<(std::ostream & os,NumberToStringConstant const & p)119 std::ostream& operator<<(std::ostream& os, NumberToStringConstant const& p) {
120 return os << p.num();
121 }
122
operator ==(StringCons const & lhs,StringCons const & rhs)123 bool operator==(StringCons const& lhs, StringCons const& rhs) {
124 // TODO(mslekova): Think if we can express this in a more readable manner
125 return *(lhs.lhs()) == *(rhs.lhs()) && *(lhs.rhs()) == *(rhs.rhs());
126 }
127
operator !=(StringCons const & lhs,StringCons const & rhs)128 bool operator!=(StringCons const& lhs, StringCons const& rhs) {
129 return !(lhs == rhs);
130 }
131
hash_value(StringCons const & p)132 size_t hash_value(StringCons const& p) {
133 return base::hash_combine(*(p.lhs()), *(p.rhs()));
134 }
135
operator <<(std::ostream & os,const StringConstantBase * base)136 std::ostream& operator<<(std::ostream& os, const StringConstantBase* base) {
137 os << "DelayedStringConstant: ";
138 switch (base->kind()) {
139 case StringConstantKind::kStringLiteral: {
140 os << *static_cast<const StringLiteral*>(base);
141 break;
142 }
143 case StringConstantKind::kNumberToStringConstant: {
144 os << *static_cast<const NumberToStringConstant*>(base);
145 break;
146 }
147 case StringConstantKind::kStringCons: {
148 os << *static_cast<const StringCons*>(base);
149 break;
150 }
151 }
152 return os;
153 }
154
operator <<(std::ostream & os,StringCons const & p)155 std::ostream& operator<<(std::ostream& os, StringCons const& p) {
156 return os << p.lhs() << ", " << p.rhs();
157 }
158
GetMaxStringConstantLength() const159 size_t StringConstantBase::GetMaxStringConstantLength() const {
160 switch (kind()) {
161 case StringConstantKind::kStringLiteral: {
162 return static_cast<const StringLiteral*>(this)
163 ->GetMaxStringConstantLength();
164 }
165 case StringConstantKind::kNumberToStringConstant: {
166 return static_cast<const NumberToStringConstant*>(this)
167 ->GetMaxStringConstantLength();
168 }
169 case StringConstantKind::kStringCons: {
170 return static_cast<const StringCons*>(this)->GetMaxStringConstantLength();
171 }
172 }
173 UNREACHABLE();
174 }
175
GetMaxStringConstantLength() const176 size_t StringLiteral::GetMaxStringConstantLength() const { return length_; }
177
GetMaxStringConstantLength() const178 size_t NumberToStringConstant::GetMaxStringConstantLength() const {
179 return kBase10MaximalLength + 1;
180 }
181
GetMaxStringConstantLength() const182 size_t StringCons::GetMaxStringConstantLength() const {
183 return lhs()->GetMaxStringConstantLength() +
184 rhs()->GetMaxStringConstantLength();
185 }
186
187 } // namespace internal
188 } // namespace v8
189