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