Commit 3deb71fb authored by bmeurer's avatar bmeurer Committed by Commit bot

[turbofan] Introduce CheckString simplified operator.

Introduce the CheckString during native context specialization when we
have string map feedback on a LOAD_IC/STORE_IC. The CheckString
operator, just like its CheckNumber pendant, renames the input and
assigns a proper type, which we will use soon to lower access operations
on Strings, i.e. charCodeAt calls or keyed accesses.

R=jarin@chromium.org
BUG=v8:4930,v8:5141

Review-Url: https://codereview.chromium.org/2181943003
Cr-Commit-Position: refs/heads/master@{#38076}
parent 9aca12a0
......@@ -625,6 +625,9 @@ bool EffectControlLinearizer::TryWireInStateEffect(Node* node,
case IrOpcode::kCheckNumber:
state = LowerCheckNumber(node, frame_state, *effect, *control);
break;
case IrOpcode::kCheckString:
state = LowerCheckString(node, frame_state, *effect, *control);
break;
case IrOpcode::kCheckIf:
state = LowerCheckIf(node, frame_state, *effect, *control);
break;
......@@ -1043,6 +1046,32 @@ EffectControlLinearizer::LowerCheckNumber(Node* node, Node* frame_state,
return ValueEffectControl(value, effect, control);
}
EffectControlLinearizer::ValueEffectControl
EffectControlLinearizer::LowerCheckString(Node* node, Node* frame_state,
Node* effect, Node* control) {
Node* value = node->InputAt(0);
Node* check0 = ObjectIsSmi(value);
control = effect =
graph()->NewNode(common()->DeoptimizeIf(DeoptimizeReason::kSmi), check0,
frame_state, effect, control);
Node* value_map = effect = graph()->NewNode(
simplified()->LoadField(AccessBuilder::ForMap()), value, effect, control);
Node* value_instance_type = effect = graph()->NewNode(
simplified()->LoadField(AccessBuilder::ForMapInstanceType()), value_map,
effect, control);
Node* check1 =
graph()->NewNode(machine()->Uint32LessThan(), value_instance_type,
jsgraph()->Uint32Constant(FIRST_NONSTRING_TYPE));
control = effect = graph()->NewNode(
common()->DeoptimizeUnless(DeoptimizeReason::kWrongInstanceType), check1,
frame_state, effect, control);
return ValueEffectControl(value, effect, control);
}
EffectControlLinearizer::ValueEffectControl
EffectControlLinearizer::LowerCheckIf(Node* node, Node* frame_state,
Node* effect, Node* control) {
......
......@@ -65,6 +65,8 @@ class EffectControlLinearizer {
Node* effect, Node* control);
ValueEffectControl LowerCheckNumber(Node* node, Node* frame_state,
Node* effect, Node* control);
ValueEffectControl LowerCheckString(Node* node, Node* frame_state,
Node* effect, Node* control);
ValueEffectControl LowerCheckIf(Node* node, Node* frame_state, Node* effect,
Node* control);
ValueEffectControl LowerCheckTaggedPointer(Node* node, Node* frame_state,
......
......@@ -154,13 +154,15 @@ Reduction JSNativeContextSpecialization::ReduceNamedAccess(
// Perform map check on {receiver}.
Type* receiver_type = access_info.receiver_type();
if (receiver_type->Is(Type::String())) {
Node* check = graph()->NewNode(simplified()->ObjectIsString(), receiver);
if (j == access_infos.size() - 1) {
this_effect = graph()->NewNode(simplified()->CheckIf(), check,
this_effect, fallthrough_control);
this_receiver = this_effect =
graph()->NewNode(simplified()->CheckString(), receiver, this_effect,
fallthrough_control);
this_control = fallthrough_control;
fallthrough_control = nullptr;
} else {
Node* check =
graph()->NewNode(simplified()->ObjectIsString(), receiver);
Node* branch =
graph()->NewNode(common()->Branch(), check, fallthrough_control);
fallthrough_control = graph()->NewNode(common()->IfFalse(), branch);
......
......@@ -267,6 +267,7 @@
V(CheckBounds) \
V(CheckIf) \
V(CheckNumber) \
V(CheckString) \
V(CheckTaggedPointer) \
V(CheckTaggedSigned) \
V(CheckFloat64Hole) \
......
......@@ -21,6 +21,7 @@ Reduction RedundancyElimination::Reduce(Node* node) {
case IrOpcode::kCheckFloat64Hole:
case IrOpcode::kCheckIf:
case IrOpcode::kCheckNumber:
case IrOpcode::kCheckString:
case IrOpcode::kCheckTaggedHole:
case IrOpcode::kCheckTaggedPointer:
case IrOpcode::kCheckTaggedSigned:
......
......@@ -1990,6 +1990,15 @@ class RepresentationSelector {
}
return;
}
case IrOpcode::kCheckString: {
if (InputIs(node, Type::String())) {
VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
if (lower()) DeferReplacement(node, node->InputAt(0));
} else {
VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
}
return;
}
case IrOpcode::kCheckTaggedPointer: {
if (InputCannotBe(node, Type::SignedSmall())) {
VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
......
......@@ -368,6 +368,7 @@ CompareOperationHints::Hint CompareOperationHintOf(const Operator* op) {
V(CheckBounds, 2, 1) \
V(CheckIf, 1, 0) \
V(CheckNumber, 1, 1) \
V(CheckString, 1, 1) \
V(CheckTaggedPointer, 1, 1) \
V(CheckTaggedSigned, 1, 1) \
V(CheckedInt32Add, 2, 1) \
......
......@@ -273,6 +273,7 @@ class SimplifiedOperatorBuilder final : public ZoneObject {
const Operator* CheckIf();
const Operator* CheckBounds();
const Operator* CheckNumber();
const Operator* CheckString();
const Operator* CheckTaggedPointer();
const Operator* CheckTaggedSigned();
......
......@@ -1806,6 +1806,11 @@ Type* Typer::Visitor::TypeCheckNumber(Node* node) {
return Type::Intersect(arg, Type::Number(), zone());
}
Type* Typer::Visitor::TypeCheckString(Node* node) {
Type* arg = Operand(node, 0);
return Type::Intersect(arg, Type::String(), zone());
}
Type* Typer::Visitor::TypeCheckIf(Node* node) {
UNREACHABLE();
return nullptr;
......
......@@ -965,6 +965,10 @@ void Verifier::Visitor::Check(Node* node) {
CheckValueInputIs(node, 0, Type::Any());
CheckUpperIs(node, Type::Number());
break;
case IrOpcode::kCheckString:
CheckValueInputIs(node, 0, Type::Any());
CheckUpperIs(node, Type::String());
break;
case IrOpcode::kCheckIf:
CheckValueInputIs(node, 0, Type::Boolean());
CheckNotTyped(node);
......
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