| // Copyright 2018 the V8 project authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "src/codegen/string-constants.h" |
| |
| #include "src/base/functional.h" |
| #include "src/objects/objects.h" |
| #include "src/objects/string-inl.h" |
| |
| namespace v8 { |
| namespace internal { |
| |
| Handle<String> StringConstantBase::AllocateStringConstant( |
| Isolate* isolate) const { |
| if (!flattened_.is_null()) { |
| return flattened_; |
| } |
| |
| Handle<String> result; |
| switch (kind()) { |
| case StringConstantKind::kStringLiteral: { |
| result = static_cast<const StringLiteral*>(this)->str(); |
| CHECK(!result.is_null()); |
| break; |
| } |
| case StringConstantKind::kNumberToStringConstant: { |
| auto num_constant = static_cast<const NumberToStringConstant*>(this); |
| Handle<Object> num_obj = |
| isolate->factory()->NewNumber(num_constant->num()); |
| result = isolate->factory()->NumberToString(num_obj); |
| CHECK(!result.is_null()); |
| break; |
| } |
| case StringConstantKind::kStringCons: { |
| Handle<String> lhs = |
| static_cast<const StringCons*>(this)->lhs()->AllocateStringConstant( |
| isolate); |
| Handle<String> rhs = |
| static_cast<const StringCons*>(this)->rhs()->AllocateStringConstant( |
| isolate); |
| result = isolate->factory()->NewConsString(lhs, rhs).ToHandleChecked(); |
| break; |
| } |
| } |
| |
| // TODO(mslekova): Normally we'd want to flatten the string here |
| // but that results in OOM for too long strings. |
| Memoize(result); |
| return flattened_; |
| } |
| |
| bool StringConstantBase::operator==(const StringConstantBase& other) const { |
| if (kind() != other.kind()) return false; |
| |
| switch (kind()) { |
| case StringConstantKind::kStringLiteral: { |
| return static_cast<const StringLiteral*>(this) == |
| static_cast<const StringLiteral*>(&other); |
| } |
| case StringConstantKind::kNumberToStringConstant: { |
| return static_cast<const NumberToStringConstant*>(this) == |
| static_cast<const NumberToStringConstant*>(&other); |
| } |
| case StringConstantKind::kStringCons: { |
| return static_cast<const StringCons*>(this) == |
| static_cast<const StringCons*>(&other); |
| } |
| } |
| UNREACHABLE(); |
| } |
| |
| size_t hash_value(StringConstantBase const& base) { |
| switch (base.kind()) { |
| case StringConstantKind::kStringLiteral: { |
| return hash_value(*static_cast<const StringLiteral*>(&base)); |
| } |
| case StringConstantKind::kNumberToStringConstant: { |
| return hash_value(*static_cast<const NumberToStringConstant*>(&base)); |
| } |
| case StringConstantKind::kStringCons: { |
| return hash_value(*static_cast<const StringCons*>(&base)); |
| } |
| } |
| UNREACHABLE(); |
| } |
| |
| bool operator==(StringLiteral const& lhs, StringLiteral const& rhs) { |
| return lhs.str().address() == rhs.str().address(); |
| } |
| |
| bool operator!=(StringLiteral const& lhs, StringLiteral const& rhs) { |
| return !(lhs == rhs); |
| } |
| |
| size_t hash_value(StringLiteral const& p) { |
| return base::hash_combine(p.str().address()); |
| } |
| |
| std::ostream& operator<<(std::ostream& os, StringLiteral const& p) { |
| return os << Brief(*p.str()); |
| } |
| |
| bool operator==(NumberToStringConstant const& lhs, |
| NumberToStringConstant const& rhs) { |
| return lhs.num() == rhs.num(); |
| } |
| |
| bool operator!=(NumberToStringConstant const& lhs, |
| NumberToStringConstant const& rhs) { |
| return !(lhs == rhs); |
| } |
| |
| size_t hash_value(NumberToStringConstant const& p) { |
| return base::hash_combine(p.num()); |
| } |
| |
| std::ostream& operator<<(std::ostream& os, NumberToStringConstant const& p) { |
| return os << p.num(); |
| } |
| |
| bool operator==(StringCons const& lhs, StringCons const& rhs) { |
| // TODO(mslekova): Think if we can express this in a more readable manner |
| return *(lhs.lhs()) == *(rhs.lhs()) && *(lhs.rhs()) == *(rhs.rhs()); |
| } |
| |
| bool operator!=(StringCons const& lhs, StringCons const& rhs) { |
| return !(lhs == rhs); |
| } |
| |
| size_t hash_value(StringCons const& p) { |
| return base::hash_combine(*(p.lhs()), *(p.rhs())); |
| } |
| |
| std::ostream& operator<<(std::ostream& os, const StringConstantBase* base) { |
| os << "DelayedStringConstant: "; |
| switch (base->kind()) { |
| case StringConstantKind::kStringLiteral: { |
| os << *static_cast<const StringLiteral*>(base); |
| break; |
| } |
| case StringConstantKind::kNumberToStringConstant: { |
| os << *static_cast<const NumberToStringConstant*>(base); |
| break; |
| } |
| case StringConstantKind::kStringCons: { |
| os << *static_cast<const StringCons*>(base); |
| break; |
| } |
| } |
| return os; |
| } |
| |
| std::ostream& operator<<(std::ostream& os, StringCons const& p) { |
| return os << p.lhs() << ", " << p.rhs(); |
| } |
| |
| size_t StringConstantBase::GetMaxStringConstantLength() const { |
| switch (kind()) { |
| case StringConstantKind::kStringLiteral: { |
| return static_cast<const StringLiteral*>(this) |
| ->GetMaxStringConstantLength(); |
| } |
| case StringConstantKind::kNumberToStringConstant: { |
| return static_cast<const NumberToStringConstant*>(this) |
| ->GetMaxStringConstantLength(); |
| } |
| case StringConstantKind::kStringCons: { |
| return static_cast<const StringCons*>(this)->GetMaxStringConstantLength(); |
| } |
| } |
| UNREACHABLE(); |
| } |
| |
| size_t StringLiteral::GetMaxStringConstantLength() const { return length_; } |
| |
| size_t NumberToStringConstant::GetMaxStringConstantLength() const { |
| return kMaxDoubleStringLength; |
| } |
| |
| size_t StringCons::GetMaxStringConstantLength() const { |
| return lhs()->GetMaxStringConstantLength() + |
| rhs()->GetMaxStringConstantLength(); |
| } |
| |
| } // namespace internal |
| } // namespace v8 |