11cb0ef41Sopenharmony_ci// Copyright 2018 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci#include "src/codegen/string-constants.h"
61cb0ef41Sopenharmony_ci
71cb0ef41Sopenharmony_ci#include "src/base/functional.h"
81cb0ef41Sopenharmony_ci#include "src/objects/objects.h"
91cb0ef41Sopenharmony_ci#include "src/objects/string-inl.h"
101cb0ef41Sopenharmony_ci
111cb0ef41Sopenharmony_cinamespace v8 {
121cb0ef41Sopenharmony_cinamespace internal {
131cb0ef41Sopenharmony_ci
141cb0ef41Sopenharmony_ciHandle<String> StringConstantBase::AllocateStringConstant(
151cb0ef41Sopenharmony_ci    Isolate* isolate) const {
161cb0ef41Sopenharmony_ci  if (!flattened_.is_null()) {
171cb0ef41Sopenharmony_ci    return flattened_;
181cb0ef41Sopenharmony_ci  }
191cb0ef41Sopenharmony_ci
201cb0ef41Sopenharmony_ci  Handle<String> result;
211cb0ef41Sopenharmony_ci  switch (kind()) {
221cb0ef41Sopenharmony_ci    case StringConstantKind::kStringLiteral: {
231cb0ef41Sopenharmony_ci      result = static_cast<const StringLiteral*>(this)->str();
241cb0ef41Sopenharmony_ci      CHECK(!result.is_null());
251cb0ef41Sopenharmony_ci      break;
261cb0ef41Sopenharmony_ci    }
271cb0ef41Sopenharmony_ci    case StringConstantKind::kNumberToStringConstant: {
281cb0ef41Sopenharmony_ci      auto num_constant = static_cast<const NumberToStringConstant*>(this);
291cb0ef41Sopenharmony_ci      Handle<Object> num_obj =
301cb0ef41Sopenharmony_ci          isolate->factory()->NewNumber(num_constant->num());
311cb0ef41Sopenharmony_ci      result = isolate->factory()->NumberToString(num_obj);
321cb0ef41Sopenharmony_ci      CHECK(!result.is_null());
331cb0ef41Sopenharmony_ci      break;
341cb0ef41Sopenharmony_ci    }
351cb0ef41Sopenharmony_ci    case StringConstantKind::kStringCons: {
361cb0ef41Sopenharmony_ci      Handle<String> lhs =
371cb0ef41Sopenharmony_ci          static_cast<const StringCons*>(this)->lhs()->AllocateStringConstant(
381cb0ef41Sopenharmony_ci              isolate);
391cb0ef41Sopenharmony_ci      Handle<String> rhs =
401cb0ef41Sopenharmony_ci          static_cast<const StringCons*>(this)->rhs()->AllocateStringConstant(
411cb0ef41Sopenharmony_ci              isolate);
421cb0ef41Sopenharmony_ci      result = isolate->factory()->NewConsString(lhs, rhs).ToHandleChecked();
431cb0ef41Sopenharmony_ci      break;
441cb0ef41Sopenharmony_ci    }
451cb0ef41Sopenharmony_ci  }
461cb0ef41Sopenharmony_ci
471cb0ef41Sopenharmony_ci  // TODO(mslekova): Normally we'd want to flatten the string here
481cb0ef41Sopenharmony_ci  // but that results in OOM for too long strings.
491cb0ef41Sopenharmony_ci  Memoize(result);
501cb0ef41Sopenharmony_ci  return flattened_;
511cb0ef41Sopenharmony_ci}
521cb0ef41Sopenharmony_ci
531cb0ef41Sopenharmony_cibool StringConstantBase::operator==(const StringConstantBase& other) const {
541cb0ef41Sopenharmony_ci  if (kind() != other.kind()) return false;
551cb0ef41Sopenharmony_ci
561cb0ef41Sopenharmony_ci  switch (kind()) {
571cb0ef41Sopenharmony_ci    case StringConstantKind::kStringLiteral: {
581cb0ef41Sopenharmony_ci      return static_cast<const StringLiteral*>(this) ==
591cb0ef41Sopenharmony_ci             static_cast<const StringLiteral*>(&other);
601cb0ef41Sopenharmony_ci    }
611cb0ef41Sopenharmony_ci    case StringConstantKind::kNumberToStringConstant: {
621cb0ef41Sopenharmony_ci      return static_cast<const NumberToStringConstant*>(this) ==
631cb0ef41Sopenharmony_ci             static_cast<const NumberToStringConstant*>(&other);
641cb0ef41Sopenharmony_ci    }
651cb0ef41Sopenharmony_ci    case StringConstantKind::kStringCons: {
661cb0ef41Sopenharmony_ci      return static_cast<const StringCons*>(this) ==
671cb0ef41Sopenharmony_ci             static_cast<const StringCons*>(&other);
681cb0ef41Sopenharmony_ci    }
691cb0ef41Sopenharmony_ci  }
701cb0ef41Sopenharmony_ci  UNREACHABLE();
711cb0ef41Sopenharmony_ci}
721cb0ef41Sopenharmony_ci
731cb0ef41Sopenharmony_cisize_t hash_value(StringConstantBase const& base) {
741cb0ef41Sopenharmony_ci  switch (base.kind()) {
751cb0ef41Sopenharmony_ci    case StringConstantKind::kStringLiteral: {
761cb0ef41Sopenharmony_ci      return hash_value(*static_cast<const StringLiteral*>(&base));
771cb0ef41Sopenharmony_ci    }
781cb0ef41Sopenharmony_ci    case StringConstantKind::kNumberToStringConstant: {
791cb0ef41Sopenharmony_ci      return hash_value(*static_cast<const NumberToStringConstant*>(&base));
801cb0ef41Sopenharmony_ci    }
811cb0ef41Sopenharmony_ci    case StringConstantKind::kStringCons: {
821cb0ef41Sopenharmony_ci      return hash_value(*static_cast<const StringCons*>(&base));
831cb0ef41Sopenharmony_ci    }
841cb0ef41Sopenharmony_ci  }
851cb0ef41Sopenharmony_ci  UNREACHABLE();
861cb0ef41Sopenharmony_ci}
871cb0ef41Sopenharmony_ci
881cb0ef41Sopenharmony_cibool operator==(StringLiteral const& lhs, StringLiteral const& rhs) {
891cb0ef41Sopenharmony_ci  return lhs.str().address() == rhs.str().address();
901cb0ef41Sopenharmony_ci}
911cb0ef41Sopenharmony_ci
921cb0ef41Sopenharmony_cibool operator!=(StringLiteral const& lhs, StringLiteral const& rhs) {
931cb0ef41Sopenharmony_ci  return !(lhs == rhs);
941cb0ef41Sopenharmony_ci}
951cb0ef41Sopenharmony_ci
961cb0ef41Sopenharmony_cisize_t hash_value(StringLiteral const& p) {
971cb0ef41Sopenharmony_ci  return base::hash_combine(p.str().address());
981cb0ef41Sopenharmony_ci}
991cb0ef41Sopenharmony_ci
1001cb0ef41Sopenharmony_cistd::ostream& operator<<(std::ostream& os, StringLiteral const& p) {
1011cb0ef41Sopenharmony_ci  return os << Brief(*p.str());
1021cb0ef41Sopenharmony_ci}
1031cb0ef41Sopenharmony_ci
1041cb0ef41Sopenharmony_cibool operator==(NumberToStringConstant const& lhs,
1051cb0ef41Sopenharmony_ci                NumberToStringConstant const& rhs) {
1061cb0ef41Sopenharmony_ci  return lhs.num() == rhs.num();
1071cb0ef41Sopenharmony_ci}
1081cb0ef41Sopenharmony_ci
1091cb0ef41Sopenharmony_cibool operator!=(NumberToStringConstant const& lhs,
1101cb0ef41Sopenharmony_ci                NumberToStringConstant const& rhs) {
1111cb0ef41Sopenharmony_ci  return !(lhs == rhs);
1121cb0ef41Sopenharmony_ci}
1131cb0ef41Sopenharmony_ci
1141cb0ef41Sopenharmony_cisize_t hash_value(NumberToStringConstant const& p) {
1151cb0ef41Sopenharmony_ci  return base::hash_combine(p.num());
1161cb0ef41Sopenharmony_ci}
1171cb0ef41Sopenharmony_ci
1181cb0ef41Sopenharmony_cistd::ostream& operator<<(std::ostream& os, NumberToStringConstant const& p) {
1191cb0ef41Sopenharmony_ci  return os << p.num();
1201cb0ef41Sopenharmony_ci}
1211cb0ef41Sopenharmony_ci
1221cb0ef41Sopenharmony_cibool operator==(StringCons const& lhs, StringCons const& rhs) {
1231cb0ef41Sopenharmony_ci  // TODO(mslekova): Think if we can express this in a more readable manner
1241cb0ef41Sopenharmony_ci  return *(lhs.lhs()) == *(rhs.lhs()) && *(lhs.rhs()) == *(rhs.rhs());
1251cb0ef41Sopenharmony_ci}
1261cb0ef41Sopenharmony_ci
1271cb0ef41Sopenharmony_cibool operator!=(StringCons const& lhs, StringCons const& rhs) {
1281cb0ef41Sopenharmony_ci  return !(lhs == rhs);
1291cb0ef41Sopenharmony_ci}
1301cb0ef41Sopenharmony_ci
1311cb0ef41Sopenharmony_cisize_t hash_value(StringCons const& p) {
1321cb0ef41Sopenharmony_ci  return base::hash_combine(*(p.lhs()), *(p.rhs()));
1331cb0ef41Sopenharmony_ci}
1341cb0ef41Sopenharmony_ci
1351cb0ef41Sopenharmony_cistd::ostream& operator<<(std::ostream& os, const StringConstantBase* base) {
1361cb0ef41Sopenharmony_ci  os << "DelayedStringConstant: ";
1371cb0ef41Sopenharmony_ci  switch (base->kind()) {
1381cb0ef41Sopenharmony_ci    case StringConstantKind::kStringLiteral: {
1391cb0ef41Sopenharmony_ci      os << *static_cast<const StringLiteral*>(base);
1401cb0ef41Sopenharmony_ci      break;
1411cb0ef41Sopenharmony_ci    }
1421cb0ef41Sopenharmony_ci    case StringConstantKind::kNumberToStringConstant: {
1431cb0ef41Sopenharmony_ci      os << *static_cast<const NumberToStringConstant*>(base);
1441cb0ef41Sopenharmony_ci      break;
1451cb0ef41Sopenharmony_ci    }
1461cb0ef41Sopenharmony_ci    case StringConstantKind::kStringCons: {
1471cb0ef41Sopenharmony_ci      os << *static_cast<const StringCons*>(base);
1481cb0ef41Sopenharmony_ci      break;
1491cb0ef41Sopenharmony_ci    }
1501cb0ef41Sopenharmony_ci  }
1511cb0ef41Sopenharmony_ci  return os;
1521cb0ef41Sopenharmony_ci}
1531cb0ef41Sopenharmony_ci
1541cb0ef41Sopenharmony_cistd::ostream& operator<<(std::ostream& os, StringCons const& p) {
1551cb0ef41Sopenharmony_ci  return os << p.lhs() << ", " << p.rhs();
1561cb0ef41Sopenharmony_ci}
1571cb0ef41Sopenharmony_ci
1581cb0ef41Sopenharmony_cisize_t StringConstantBase::GetMaxStringConstantLength() const {
1591cb0ef41Sopenharmony_ci  switch (kind()) {
1601cb0ef41Sopenharmony_ci    case StringConstantKind::kStringLiteral: {
1611cb0ef41Sopenharmony_ci      return static_cast<const StringLiteral*>(this)
1621cb0ef41Sopenharmony_ci          ->GetMaxStringConstantLength();
1631cb0ef41Sopenharmony_ci    }
1641cb0ef41Sopenharmony_ci    case StringConstantKind::kNumberToStringConstant: {
1651cb0ef41Sopenharmony_ci      return static_cast<const NumberToStringConstant*>(this)
1661cb0ef41Sopenharmony_ci          ->GetMaxStringConstantLength();
1671cb0ef41Sopenharmony_ci    }
1681cb0ef41Sopenharmony_ci    case StringConstantKind::kStringCons: {
1691cb0ef41Sopenharmony_ci      return static_cast<const StringCons*>(this)->GetMaxStringConstantLength();
1701cb0ef41Sopenharmony_ci    }
1711cb0ef41Sopenharmony_ci  }
1721cb0ef41Sopenharmony_ci  UNREACHABLE();
1731cb0ef41Sopenharmony_ci}
1741cb0ef41Sopenharmony_ci
1751cb0ef41Sopenharmony_cisize_t StringLiteral::GetMaxStringConstantLength() const { return length_; }
1761cb0ef41Sopenharmony_ci
1771cb0ef41Sopenharmony_cisize_t NumberToStringConstant::GetMaxStringConstantLength() const {
1781cb0ef41Sopenharmony_ci  return kMaxDoubleStringLength;
1791cb0ef41Sopenharmony_ci}
1801cb0ef41Sopenharmony_ci
1811cb0ef41Sopenharmony_cisize_t StringCons::GetMaxStringConstantLength() const {
1821cb0ef41Sopenharmony_ci  return lhs()->GetMaxStringConstantLength() +
1831cb0ef41Sopenharmony_ci         rhs()->GetMaxStringConstantLength();
1841cb0ef41Sopenharmony_ci}
1851cb0ef41Sopenharmony_ci
1861cb0ef41Sopenharmony_ci}  // namespace internal
1871cb0ef41Sopenharmony_ci}  // namespace v8
188