• 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/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