Commit 481ea63d authored by Peter Marshall's avatar Peter Marshall Committed by Commit Bot

[turbofan] Add CheckSeqString so that we have type info for CharCodeAt.

Bug: v8:6391
Change-Id: If63078c756d9cfb00e515fae005755c4ed8b12f7
Reviewed-on: https://chromium-review.googlesource.com/512803Reviewed-by: 's avatarJaroslav Sevcik <jarin@chromium.org>
Reviewed-by: 's avatarBenedikt Meurer <bmeurer@chromium.org>
Commit-Queue: Peter Marshall <petermarshall@chromium.org>
Cr-Commit-Position: refs/heads/master@{#45549}
parent aa0c8dcc
......@@ -647,6 +647,9 @@ bool EffectControlLinearizer::TryWireInStateEffect(Node* node,
case IrOpcode::kCheckString:
result = LowerCheckString(node, frame_state);
break;
case IrOpcode::kCheckSeqString:
result = LowerCheckSeqString(node, frame_state);
break;
case IrOpcode::kCheckInternalizedString:
result = LowerCheckInternalizedString(node, frame_state);
break;
......@@ -1330,6 +1333,27 @@ Node* EffectControlLinearizer::LowerCheckString(Node* node, Node* frame_state) {
return value;
}
Node* EffectControlLinearizer::LowerCheckSeqString(Node* node,
Node* frame_state) {
Node* value = node->InputAt(0);
Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
Node* value_instance_type =
__ LoadField(AccessBuilder::ForMapInstanceType(), value_map);
Node* is_string = __ Uint32LessThan(value_instance_type,
__ Uint32Constant(FIRST_NONSTRING_TYPE));
Node* is_sequential =
__ Word32Equal(__ Word32And(value_instance_type,
__ Int32Constant(kStringRepresentationMask)),
__ Int32Constant(kSeqStringTag));
Node* is_sequential_string = __ Word32And(is_string, is_sequential);
__ DeoptimizeUnless(DeoptimizeReason::kWrongInstanceType,
is_sequential_string, frame_state);
return value;
}
Node* EffectControlLinearizer::LowerCheckInternalizedString(Node* node,
Node* frame_state) {
Node* value = node->InputAt(0);
......
......@@ -58,6 +58,7 @@ class V8_EXPORT_PRIVATE EffectControlLinearizer {
Node* LowerCheckNumber(Node* node, Node* frame_state);
Node* LowerCheckReceiver(Node* node, Node* frame_state);
Node* LowerCheckString(Node* node, Node* frame_state);
Node* LowerCheckSeqString(Node* node, Node* frame_state);
Node* LowerCheckSymbol(Node* node, Node* frame_state);
Node* LowerCheckIf(Node* node, Node* frame_state);
Node* LowerCheckedInt32Add(Node* node, Node* frame_state);
......
......@@ -1899,7 +1899,9 @@ Node* GetStringWitness(Node* node) {
// it's {receiver}, and if so use that renaming as {receiver} for
// the lowering below.
for (Node* dominator = effect;;) {
if (dominator->opcode() == IrOpcode::kCheckString &&
if ((dominator->opcode() == IrOpcode::kCheckString ||
dominator->opcode() == IrOpcode::kCheckInternalizedString ||
dominator->opcode() == IrOpcode::kCheckSeqString) &&
NodeProperties::IsSame(dominator->InputAt(0), receiver)) {
return dominator;
}
......
......@@ -45,14 +45,23 @@ bool HasOnlyNumberMaps(MapHandles const& maps) {
return true;
}
template <typename T>
bool HasOnlyStringMaps(T const& maps) {
bool HasOnlyStringMaps(MapHandles const& maps) {
for (auto map : maps) {
if (!map->IsStringMap()) return false;
}
return true;
}
bool HasOnlySequentialStringMaps(MapHandles const& maps) {
for (auto map : maps) {
if (!map->IsStringMap()) return false;
if (!StringShape(map->instance_type()).IsSequential()) {
return false;
}
}
return true;
}
} // namespace
struct JSNativeContextSpecialization::ScriptContextTableLookupResult {
......@@ -770,10 +779,16 @@ Reduction JSNativeContextSpecialization::ReduceNamedAccess(
if (access_infos.size() == 1) {
PropertyAccessInfo access_info = access_infos.front();
if (HasOnlyStringMaps(access_info.receiver_maps())) {
if (HasOnlySequentialStringMaps(access_info.receiver_maps())) {
receiver = effect = graph()->NewNode(simplified()->CheckSeqString(),
receiver, effect, control);
} else {
// Monormorphic string access (ignoring the fact that there are multiple
// String maps).
receiver = effect = graph()->NewNode(simplified()->CheckString(),
receiver, effect, control);
}
} else if (HasOnlyNumberMaps(access_info.receiver_maps())) {
// Monomorphic number access (we also deal with Smis here).
receiver = effect = graph()->NewNode(simplified()->CheckNumber(),
......
......@@ -322,6 +322,7 @@
V(CheckInternalizedString) \
V(CheckReceiver) \
V(CheckString) \
V(CheckSeqString) \
V(CheckSymbol) \
V(CheckSmi) \
V(CheckHeapObject) \
......
......@@ -27,6 +27,7 @@ Reduction RedundancyElimination::Reduce(Node* node) {
case IrOpcode::kCheckReceiver:
case IrOpcode::kCheckSmi:
case IrOpcode::kCheckString:
case IrOpcode::kCheckSeqString:
case IrOpcode::kCheckTaggedHole:
case IrOpcode::kCheckedFloat64ToInt32:
case IrOpcode::kCheckedInt32Add:
......
......@@ -2443,6 +2443,17 @@ class RepresentationSelector {
VisitCheck(node, Type::Symbol(), lowering);
return;
}
case IrOpcode::kCheckSeqString: {
if (InputIs(node, Type::SeqString())) {
VisitUnop(node, UseInfo::AnyTagged(),
MachineRepresentation::kTaggedPointer);
if (lower()) DeferReplacement(node, node->InputAt(0));
} else {
VisitUnop(node, UseInfo::CheckedHeapObjectAsTaggedPointer(),
MachineRepresentation::kTaggedPointer);
}
return;
}
case IrOpcode::kAllocate: {
ProcessInput(node, 0, UseInfo::TruncatingWord32());
......
......@@ -523,6 +523,7 @@ UnicodeEncoding UnicodeEncodingOf(const Operator* op) {
V(CheckReceiver, 1, 1) \
V(CheckSmi, 1, 1) \
V(CheckString, 1, 1) \
V(CheckSeqString, 1, 1) \
V(CheckSymbol, 1, 1) \
V(CheckTaggedHole, 1, 1) \
V(CheckedInt32Add, 2, 1) \
......
......@@ -415,6 +415,7 @@ class V8_EXPORT_PRIVATE SimplifiedOperatorBuilder final
const Operator* CheckNumber();
const Operator* CheckSmi();
const Operator* CheckString();
const Operator* CheckSeqString();
const Operator* CheckSymbol();
const Operator* CheckReceiver();
......
......@@ -82,6 +82,8 @@ Reduction TypedOptimization::Reduce(Node* node) {
return ReduceCheckNumber(node);
case IrOpcode::kCheckString:
return ReduceCheckString(node);
case IrOpcode::kCheckSeqString:
return ReduceCheckSeqString(node);
case IrOpcode::kLoadField:
return ReduceLoadField(node);
case IrOpcode::kNumberCeil:
......@@ -174,6 +176,16 @@ Reduction TypedOptimization::ReduceCheckString(Node* node) {
return NoChange();
}
Reduction TypedOptimization::ReduceCheckSeqString(Node* node) {
Node* const input = NodeProperties::GetValueInput(node, 0);
Type* const input_type = NodeProperties::GetType(input);
if (input_type->Is(Type::SeqString())) {
ReplaceWithValue(node, input);
return Replace(input);
}
return NoChange();
}
Reduction TypedOptimization::ReduceLoadField(Node* node) {
Node* const object = NodeProperties::GetValueInput(node, 0);
Type* const object_type = NodeProperties::GetType(object);
......
......@@ -46,6 +46,7 @@ class V8_EXPORT_PRIVATE TypedOptimization final
Reduction ReduceCheckMaps(Node* node);
Reduction ReduceCheckNumber(Node* node);
Reduction ReduceCheckString(Node* node);
Reduction ReduceCheckSeqString(Node* node);
Reduction ReduceLoadField(Node* node);
Reduction ReduceNumberFloor(Node* node);
Reduction ReduceNumberRoundop(Node* node);
......
......@@ -1838,6 +1838,11 @@ Type* Typer::Visitor::TypeCheckString(Node* node) {
return Type::Intersect(arg, Type::String(), zone());
}
Type* Typer::Visitor::TypeCheckSeqString(Node* node) {
Type* arg = Operand(node, 0);
return Type::Intersect(arg, Type::SeqString(), zone());
}
Type* Typer::Visitor::TypeCheckSymbol(Node* node) {
Type* arg = Operand(node, 0);
return Type::Intersect(arg, Type::Symbol(), zone());
......
......@@ -1184,10 +1184,13 @@ void Verifier::Visitor::Check(Node* node) {
CheckValueInputIs(node, 0, Type::Any());
CheckTypeIs(node, Type::String());
break;
case IrOpcode::kCheckSeqString:
CheckValueInputIs(node, 0, Type::Any());
CheckTypeIs(node, Type::SeqString());
break;
case IrOpcode::kCheckSymbol:
CheckValueInputIs(node, 0, Type::Any());
CheckTypeIs(node, Type::Symbol());
break;
case IrOpcode::kCheckedInt32Add:
case IrOpcode::kCheckedInt32Sub:
......
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