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 11namespace v8 { 12namespace internal { 13 14Handle<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 53bool 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 73size_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 88bool operator==(StringLiteral const& lhs, StringLiteral const& rhs) { 89 return lhs.str().address() == rhs.str().address(); 90} 91 92bool operator!=(StringLiteral const& lhs, StringLiteral const& rhs) { 93 return !(lhs == rhs); 94} 95 96size_t hash_value(StringLiteral const& p) { 97 return base::hash_combine(p.str().address()); 98} 99 100std::ostream& operator<<(std::ostream& os, StringLiteral const& p) { 101 return os << Brief(*p.str()); 102} 103 104bool operator==(NumberToStringConstant const& lhs, 105 NumberToStringConstant const& rhs) { 106 return lhs.num() == rhs.num(); 107} 108 109bool operator!=(NumberToStringConstant const& lhs, 110 NumberToStringConstant const& rhs) { 111 return !(lhs == rhs); 112} 113 114size_t hash_value(NumberToStringConstant const& p) { 115 return base::hash_combine(p.num()); 116} 117 118std::ostream& operator<<(std::ostream& os, NumberToStringConstant const& p) { 119 return os << p.num(); 120} 121 122bool 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 127bool operator!=(StringCons const& lhs, StringCons const& rhs) { 128 return !(lhs == rhs); 129} 130 131size_t hash_value(StringCons const& p) { 132 return base::hash_combine(*(p.lhs()), *(p.rhs())); 133} 134 135std::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 154std::ostream& operator<<(std::ostream& os, StringCons const& p) { 155 return os << p.lhs() << ", " << p.rhs(); 156} 157 158size_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 175size_t StringLiteral::GetMaxStringConstantLength() const { return length_; } 176 177size_t NumberToStringConstant::GetMaxStringConstantLength() const { 178 return kMaxDoubleStringLength; 179} 180 181size_t StringCons::GetMaxStringConstantLength() const { 182 return lhs()->GetMaxStringConstantLength() + 183 rhs()->GetMaxStringConstantLength(); 184} 185 186} // namespace internal 187} // namespace v8 188