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, ...@@ -647,6 +647,9 @@ bool EffectControlLinearizer::TryWireInStateEffect(Node* node,
case IrOpcode::kCheckString: case IrOpcode::kCheckString:
result = LowerCheckString(node, frame_state); result = LowerCheckString(node, frame_state);
break; break;
case IrOpcode::kCheckSeqString:
result = LowerCheckSeqString(node, frame_state);
break;
case IrOpcode::kCheckInternalizedString: case IrOpcode::kCheckInternalizedString:
result = LowerCheckInternalizedString(node, frame_state); result = LowerCheckInternalizedString(node, frame_state);
break; break;
...@@ -1330,6 +1333,27 @@ Node* EffectControlLinearizer::LowerCheckString(Node* node, Node* frame_state) { ...@@ -1330,6 +1333,27 @@ Node* EffectControlLinearizer::LowerCheckString(Node* node, Node* frame_state) {
return value; 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* EffectControlLinearizer::LowerCheckInternalizedString(Node* node,
Node* frame_state) { Node* frame_state) {
Node* value = node->InputAt(0); Node* value = node->InputAt(0);
......
...@@ -58,6 +58,7 @@ class V8_EXPORT_PRIVATE EffectControlLinearizer { ...@@ -58,6 +58,7 @@ class V8_EXPORT_PRIVATE EffectControlLinearizer {
Node* LowerCheckNumber(Node* node, Node* frame_state); Node* LowerCheckNumber(Node* node, Node* frame_state);
Node* LowerCheckReceiver(Node* node, Node* frame_state); Node* LowerCheckReceiver(Node* node, Node* frame_state);
Node* LowerCheckString(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* LowerCheckSymbol(Node* node, Node* frame_state);
Node* LowerCheckIf(Node* node, Node* frame_state); Node* LowerCheckIf(Node* node, Node* frame_state);
Node* LowerCheckedInt32Add(Node* node, Node* frame_state); Node* LowerCheckedInt32Add(Node* node, Node* frame_state);
......
...@@ -1899,7 +1899,9 @@ Node* GetStringWitness(Node* node) { ...@@ -1899,7 +1899,9 @@ Node* GetStringWitness(Node* node) {
// it's {receiver}, and if so use that renaming as {receiver} for // it's {receiver}, and if so use that renaming as {receiver} for
// the lowering below. // the lowering below.
for (Node* dominator = effect;;) { 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)) { NodeProperties::IsSame(dominator->InputAt(0), receiver)) {
return dominator; return dominator;
} }
......
...@@ -45,14 +45,23 @@ bool HasOnlyNumberMaps(MapHandles const& maps) { ...@@ -45,14 +45,23 @@ bool HasOnlyNumberMaps(MapHandles const& maps) {
return true; return true;
} }
template <typename T> bool HasOnlyStringMaps(MapHandles const& maps) {
bool HasOnlyStringMaps(T const& maps) {
for (auto map : maps) { for (auto map : maps) {
if (!map->IsStringMap()) return false; if (!map->IsStringMap()) return false;
} }
return true; 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 } // namespace
struct JSNativeContextSpecialization::ScriptContextTableLookupResult { struct JSNativeContextSpecialization::ScriptContextTableLookupResult {
...@@ -770,10 +779,16 @@ Reduction JSNativeContextSpecialization::ReduceNamedAccess( ...@@ -770,10 +779,16 @@ Reduction JSNativeContextSpecialization::ReduceNamedAccess(
if (access_infos.size() == 1) { if (access_infos.size() == 1) {
PropertyAccessInfo access_info = access_infos.front(); PropertyAccessInfo access_info = access_infos.front();
if (HasOnlyStringMaps(access_info.receiver_maps())) { if (HasOnlyStringMaps(access_info.receiver_maps())) {
// Monormorphic string access (ignoring the fact that there are multiple if (HasOnlySequentialStringMaps(access_info.receiver_maps())) {
// String maps). receiver = effect = graph()->NewNode(simplified()->CheckSeqString(),
receiver = effect = graph()->NewNode(simplified()->CheckString(), receiver, effect, control);
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())) { } else if (HasOnlyNumberMaps(access_info.receiver_maps())) {
// Monomorphic number access (we also deal with Smis here). // Monomorphic number access (we also deal with Smis here).
receiver = effect = graph()->NewNode(simplified()->CheckNumber(), receiver = effect = graph()->NewNode(simplified()->CheckNumber(),
......
...@@ -322,6 +322,7 @@ ...@@ -322,6 +322,7 @@
V(CheckInternalizedString) \ V(CheckInternalizedString) \
V(CheckReceiver) \ V(CheckReceiver) \
V(CheckString) \ V(CheckString) \
V(CheckSeqString) \
V(CheckSymbol) \ V(CheckSymbol) \
V(CheckSmi) \ V(CheckSmi) \
V(CheckHeapObject) \ V(CheckHeapObject) \
......
...@@ -27,6 +27,7 @@ Reduction RedundancyElimination::Reduce(Node* node) { ...@@ -27,6 +27,7 @@ Reduction RedundancyElimination::Reduce(Node* node) {
case IrOpcode::kCheckReceiver: case IrOpcode::kCheckReceiver:
case IrOpcode::kCheckSmi: case IrOpcode::kCheckSmi:
case IrOpcode::kCheckString: case IrOpcode::kCheckString:
case IrOpcode::kCheckSeqString:
case IrOpcode::kCheckTaggedHole: case IrOpcode::kCheckTaggedHole:
case IrOpcode::kCheckedFloat64ToInt32: case IrOpcode::kCheckedFloat64ToInt32:
case IrOpcode::kCheckedInt32Add: case IrOpcode::kCheckedInt32Add:
......
...@@ -2443,6 +2443,17 @@ class RepresentationSelector { ...@@ -2443,6 +2443,17 @@ class RepresentationSelector {
VisitCheck(node, Type::Symbol(), lowering); VisitCheck(node, Type::Symbol(), lowering);
return; 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: { case IrOpcode::kAllocate: {
ProcessInput(node, 0, UseInfo::TruncatingWord32()); ProcessInput(node, 0, UseInfo::TruncatingWord32());
......
...@@ -523,6 +523,7 @@ UnicodeEncoding UnicodeEncodingOf(const Operator* op) { ...@@ -523,6 +523,7 @@ UnicodeEncoding UnicodeEncodingOf(const Operator* op) {
V(CheckReceiver, 1, 1) \ V(CheckReceiver, 1, 1) \
V(CheckSmi, 1, 1) \ V(CheckSmi, 1, 1) \
V(CheckString, 1, 1) \ V(CheckString, 1, 1) \
V(CheckSeqString, 1, 1) \
V(CheckSymbol, 1, 1) \ V(CheckSymbol, 1, 1) \
V(CheckTaggedHole, 1, 1) \ V(CheckTaggedHole, 1, 1) \
V(CheckedInt32Add, 2, 1) \ V(CheckedInt32Add, 2, 1) \
......
...@@ -415,6 +415,7 @@ class V8_EXPORT_PRIVATE SimplifiedOperatorBuilder final ...@@ -415,6 +415,7 @@ class V8_EXPORT_PRIVATE SimplifiedOperatorBuilder final
const Operator* CheckNumber(); const Operator* CheckNumber();
const Operator* CheckSmi(); const Operator* CheckSmi();
const Operator* CheckString(); const Operator* CheckString();
const Operator* CheckSeqString();
const Operator* CheckSymbol(); const Operator* CheckSymbol();
const Operator* CheckReceiver(); const Operator* CheckReceiver();
......
...@@ -82,6 +82,8 @@ Reduction TypedOptimization::Reduce(Node* node) { ...@@ -82,6 +82,8 @@ Reduction TypedOptimization::Reduce(Node* node) {
return ReduceCheckNumber(node); return ReduceCheckNumber(node);
case IrOpcode::kCheckString: case IrOpcode::kCheckString:
return ReduceCheckString(node); return ReduceCheckString(node);
case IrOpcode::kCheckSeqString:
return ReduceCheckSeqString(node);
case IrOpcode::kLoadField: case IrOpcode::kLoadField:
return ReduceLoadField(node); return ReduceLoadField(node);
case IrOpcode::kNumberCeil: case IrOpcode::kNumberCeil:
...@@ -174,6 +176,16 @@ Reduction TypedOptimization::ReduceCheckString(Node* node) { ...@@ -174,6 +176,16 @@ Reduction TypedOptimization::ReduceCheckString(Node* node) {
return NoChange(); 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) { Reduction TypedOptimization::ReduceLoadField(Node* node) {
Node* const object = NodeProperties::GetValueInput(node, 0); Node* const object = NodeProperties::GetValueInput(node, 0);
Type* const object_type = NodeProperties::GetType(object); Type* const object_type = NodeProperties::GetType(object);
......
...@@ -46,6 +46,7 @@ class V8_EXPORT_PRIVATE TypedOptimization final ...@@ -46,6 +46,7 @@ class V8_EXPORT_PRIVATE TypedOptimization final
Reduction ReduceCheckMaps(Node* node); Reduction ReduceCheckMaps(Node* node);
Reduction ReduceCheckNumber(Node* node); Reduction ReduceCheckNumber(Node* node);
Reduction ReduceCheckString(Node* node); Reduction ReduceCheckString(Node* node);
Reduction ReduceCheckSeqString(Node* node);
Reduction ReduceLoadField(Node* node); Reduction ReduceLoadField(Node* node);
Reduction ReduceNumberFloor(Node* node); Reduction ReduceNumberFloor(Node* node);
Reduction ReduceNumberRoundop(Node* node); Reduction ReduceNumberRoundop(Node* node);
......
...@@ -1838,6 +1838,11 @@ Type* Typer::Visitor::TypeCheckString(Node* node) { ...@@ -1838,6 +1838,11 @@ Type* Typer::Visitor::TypeCheckString(Node* node) {
return Type::Intersect(arg, Type::String(), zone()); 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* Typer::Visitor::TypeCheckSymbol(Node* node) {
Type* arg = Operand(node, 0); Type* arg = Operand(node, 0);
return Type::Intersect(arg, Type::Symbol(), zone()); return Type::Intersect(arg, Type::Symbol(), zone());
......
...@@ -1184,10 +1184,13 @@ void Verifier::Visitor::Check(Node* node) { ...@@ -1184,10 +1184,13 @@ void Verifier::Visitor::Check(Node* node) {
CheckValueInputIs(node, 0, Type::Any()); CheckValueInputIs(node, 0, Type::Any());
CheckTypeIs(node, Type::String()); CheckTypeIs(node, Type::String());
break; break;
case IrOpcode::kCheckSeqString:
CheckValueInputIs(node, 0, Type::Any());
CheckTypeIs(node, Type::SeqString());
break;
case IrOpcode::kCheckSymbol: case IrOpcode::kCheckSymbol:
CheckValueInputIs(node, 0, Type::Any()); CheckValueInputIs(node, 0, Type::Any());
CheckTypeIs(node, Type::Symbol()); CheckTypeIs(node, Type::Symbol());
break;
case IrOpcode::kCheckedInt32Add: case IrOpcode::kCheckedInt32Add:
case IrOpcode::kCheckedInt32Sub: 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