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