blob: 92a5e97396248b29d40df83ab73310f5b70bc6b6 [file] [log] [blame]
// 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/numbers/dtoa.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 kBase10MaximalLength + 1;
}
size_t StringCons::GetMaxStringConstantLength() const {
return lhs()->GetMaxStringConstantLength() +
rhs()->GetMaxStringConstantLength();
}
} // namespace internal
} // namespace v8