• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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