Commit d727c9b4 authored by Santiago Aboy Solanes's avatar Santiago Aboy Solanes Committed by Commit Bot

[compiler] Make StringRef::length() return an optional value

We are planning on moving String to kNeverSerialized. For this, we are
modifying its methods to bail out if they encounter a NeverSerialized
non-internalized String.

Bug: v8:7790
Change-Id: Ia83c1385e53707ddec374e1730963c29b928a08c
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2615420Reviewed-by: 's avatarGeorg Neis <neis@chromium.org>
Commit-Queue: Santiago Aboy Solanes <solanes@chromium.org>
Cr-Commit-Position: refs/heads/master@{#71975}
parent d4ecac6b
......@@ -834,7 +834,7 @@ class StringRef : public NameRef {
Handle<String> object() const;
int length() const;
base::Optional<int> length() const;
uint16_t GetFirstChar();
base::Optional<double> ToNumber();
bool IsSeqString() const;
......
......@@ -6009,7 +6009,7 @@ Reduction JSCallReducer::ReduceStringPrototypeStartsWith(Node* node) {
ObjectRef target_ref = m.Ref(broker());
if (target_ref.IsString()) {
StringRef str = target_ref.AsString();
if (str.length() == 1) {
if (str.length().has_value() && str.length().value() == 1) {
receiver = effect = graph()->NewNode(
simplified()->CheckString(p.feedback()), receiver, effect, control);
......
......@@ -3064,9 +3064,17 @@ bool MapRef::IsUnboxedDoubleField(InternalIndex descriptor_index) const {
.is_unboxed_double_field;
}
int StringRef::length() const {
base::Optional<int> StringRef::length() const {
if (data_->should_access_heap()) {
return object()->synchronized_length();
if (data_->kind() == kNeverSerializedHeapObject &&
!this->IsInternalizedString()) {
TRACE_BROKER_MISSING(
broker(),
"length for kNeverSerialized non-internalized string " << *this);
return base::nullopt;
} else {
return object()->synchronized_length();
}
}
return data()->AsString()->length();
}
......
......@@ -176,7 +176,7 @@ Reduction JSNativeContextSpecialization::ReduceJSToString(Node* node) {
return NoChange();
}
const StringConstantBase*
base::Optional<const StringConstantBase*>
JSNativeContextSpecialization::CreateDelayedStringConstant(Node* node) {
if (node->opcode() == IrOpcode::kDelayedStringConstant) {
return StringConstantBaseOf(node->op());
......@@ -189,8 +189,9 @@ JSNativeContextSpecialization::CreateDelayedStringConstant(Node* node) {
HeapObjectMatcher matcher(node);
if (matcher.HasResolvedValue() && matcher.Ref(broker()).IsString()) {
StringRef s = matcher.Ref(broker()).AsString();
if (!s.length().has_value()) return base::nullopt;
return shared_zone()->New<StringLiteral>(
s.object(), static_cast<size_t>(s.length()));
s.object(), static_cast<size_t>(s.length().value()));
} else {
UNREACHABLE();
}
......@@ -329,10 +330,14 @@ Reduction JSNativeContextSpecialization::ReduceJSAdd(Node* node) {
// string constant and the addition won't throw due to too long result.
if (*lhs_len + *rhs_len <= String::kMaxLength &&
(IsStringConstant(broker(), lhs) || IsStringConstant(broker(), rhs))) {
const StringConstantBase* left = CreateDelayedStringConstant(lhs);
const StringConstantBase* right = CreateDelayedStringConstant(rhs);
base::Optional<const StringConstantBase*> left =
CreateDelayedStringConstant(lhs);
if (!left.has_value()) return NoChange();
base::Optional<const StringConstantBase*> right =
CreateDelayedStringConstant(rhs);
if (!right.has_value()) return NoChange();
const StringConstantBase* cons =
shared_zone()->New<StringCons>(left, right);
shared_zone()->New<StringCons>(left.value(), right.value());
Node* reduced = graph()->NewNode(common()->DelayedStringConstant(cons));
ReplaceWithValue(node, reduced);
......@@ -1480,7 +1485,8 @@ Reduction JSNativeContextSpecialization::ReduceJSLoadNamed(Node* node) {
} else if (object.IsString() &&
name.equals(ObjectRef(broker(), factory()->length_string()))) {
// Constant-fold "length" property on constant strings.
Node* value = jsgraph()->Constant(object.AsString().length());
if (!object.AsString().length().has_value()) return NoChange();
Node* value = jsgraph()->Constant(object.AsString().length().value());
ReplaceWithValue(node, value);
return Replace(value);
}
......@@ -1978,7 +1984,9 @@ Reduction JSNativeContextSpecialization::ReduceElementLoadFromHeapConstant(
if (receiver_ref.IsString()) {
DCHECK_NE(access_mode, AccessMode::kHas);
// Ensure that {key} is less than {receiver} length.
Node* length = jsgraph()->Constant(receiver_ref.AsString().length());
if (!receiver_ref.AsString().length().has_value()) return NoChange();
Node* length =
jsgraph()->Constant(receiver_ref.AsString().length().value());
// Load the single character string from {receiver} or yield
// undefined if the {key} is out of bounds (depending on the
......
......@@ -129,7 +129,8 @@ class V8_EXPORT_PRIVATE JSNativeContextSpecialization final
Reduction ReduceJSLoadPropertyWithEnumeratedKey(Node* node);
const StringConstantBase* CreateDelayedStringConstant(Node* node);
base::Optional<const StringConstantBase*> CreateDelayedStringConstant(
Node* node);
// A triple of nodes that represents a continuation.
class ValueEffectControl final {
......
......@@ -109,11 +109,14 @@ class JSBinopReduction final {
JSHeapBroker* broker = lowering_->broker();
if (m.right().HasResolvedValue() && m.right().Ref(broker).IsString()) {
StringRef right_string = m.right().Ref(broker).AsString();
if (right_string.length() >= ConsString::kMinLength) return true;
if (right_string.length().has_value() &&
right_string.length().value() >= ConsString::kMinLength)
return true;
}
if (m.left().HasResolvedValue() && m.left().Ref(broker).IsString()) {
StringRef left_string = m.left().Ref(broker).AsString();
if (left_string.length() >= ConsString::kMinLength) {
if (left_string.length().has_value() &&
left_string.length().value() >= ConsString::kMinLength) {
// The invariant for ConsString requires the left hand side to be
// a sequential or external string if the right hand side is the
// empty string. Since we don't know anything about the right hand
......
......@@ -432,7 +432,7 @@ Reduction TypedOptimization::
Node* comparison, const StringRef& string, bool inverted) {
switch (comparison->opcode()) {
case IrOpcode::kStringEqual:
if (string.length() != 1) {
if (string.length().has_value() && string.length().value() != 1) {
// String.fromCharCode(x) always has length 1.
return Replace(jsgraph()->BooleanConstant(false));
}
......@@ -440,7 +440,7 @@ Reduction TypedOptimization::
case IrOpcode::kStringLessThan:
V8_FALLTHROUGH;
case IrOpcode::kStringLessThanOrEqual:
if (string.length() == 0) {
if (string.length().has_value() && string.length().value() == 0) {
// String.fromCharCode(x) <= "" is always false,
// "" < String.fromCharCode(x) is always true.
return Replace(jsgraph()->BooleanConstant(inverted));
......@@ -487,7 +487,7 @@ TypedOptimization::TryReduceStringComparisonOfStringFromSingleCharCode(
Node* number_comparison = nullptr;
if (inverted) {
// "x..." <= String.fromCharCode(z) is true if x < z.
if (string.length() > 1 &&
if (string.length().has_value() && string.length().value() > 1 &&
comparison->opcode() == IrOpcode::kStringLessThanOrEqual) {
comparison_op = simplified()->NumberLessThan();
}
......@@ -495,7 +495,7 @@ TypedOptimization::TryReduceStringComparisonOfStringFromSingleCharCode(
graph()->NewNode(comparison_op, constant_repl, from_char_code_repl);
} else {
// String.fromCharCode(z) < "x..." is true if z <= x.
if (string.length() > 1 &&
if (string.length().has_value() && string.length().value() > 1 &&
comparison->opcode() == IrOpcode::kStringLessThan) {
comparison_op = simplified()->NumberLessThanOrEqual();
}
......@@ -557,9 +557,11 @@ Reduction TypedOptimization::ReduceStringLength(Node* node) {
// Constant-fold the String::length of the {input}.
HeapObjectMatcher m(input);
if (m.Ref(broker()).IsString()) {
uint32_t const length = m.Ref(broker()).AsString().length();
Node* value = jsgraph()->Constant(length);
return Replace(value);
if (m.Ref(broker()).AsString().length().has_value()) {
uint32_t const length = m.Ref(broker()).AsString().length().value();
Node* value = jsgraph()->Constant(length);
return Replace(value);
}
}
break;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment