Merge V8 5.5.372.32
Test: Manual, built and ran D8
Change-Id: I831a5491f74342c2675bb6fe1e24a2258e493758
diff --git a/src/compiler/effect-control-linearizer.cc b/src/compiler/effect-control-linearizer.cc
index 9cc6ddc..4e53e5d 100644
--- a/src/compiler/effect-control-linearizer.cc
+++ b/src/compiler/effect-control-linearizer.cc
@@ -265,7 +265,6 @@
Node* phi_false = graph->NewNode(phi->op(), input_count + 1, inputs);
if (phi->UseCount() == 0) {
DCHECK_EQ(phi->opcode(), IrOpcode::kEffectPhi);
- DCHECK_EQ(input_count, block->SuccessorCount());
} else {
for (Edge edge : phi->use_edges()) {
Node* control = NodeProperties::GetControlInput(edge.from());
@@ -616,6 +615,9 @@
case IrOpcode::kChangeTaggedToFloat64:
state = LowerChangeTaggedToFloat64(node, *effect, *control);
break;
+ case IrOpcode::kTruncateTaggedToBit:
+ state = LowerTruncateTaggedToBit(node, *effect, *control);
+ break;
case IrOpcode::kTruncateTaggedToFloat64:
state = LowerTruncateTaggedToFloat64(node, *effect, *control);
break;
@@ -634,11 +636,8 @@
case IrOpcode::kCheckIf:
state = LowerCheckIf(node, frame_state, *effect, *control);
break;
- case IrOpcode::kCheckTaggedPointer:
- state = LowerCheckTaggedPointer(node, frame_state, *effect, *control);
- break;
- case IrOpcode::kCheckTaggedSigned:
- state = LowerCheckTaggedSigned(node, frame_state, *effect, *control);
+ case IrOpcode::kCheckHeapObject:
+ state = LowerCheckHeapObject(node, frame_state, *effect, *control);
break;
case IrOpcode::kCheckedInt32Add:
state = LowerCheckedInt32Add(node, frame_state, *effect, *control);
@@ -661,9 +660,17 @@
case IrOpcode::kCheckedInt32Mul:
state = LowerCheckedInt32Mul(node, frame_state, *effect, *control);
break;
+ case IrOpcode::kCheckedInt32ToTaggedSigned:
+ state =
+ LowerCheckedInt32ToTaggedSigned(node, frame_state, *effect, *control);
+ break;
case IrOpcode::kCheckedUint32ToInt32:
state = LowerCheckedUint32ToInt32(node, frame_state, *effect, *control);
break;
+ case IrOpcode::kCheckedUint32ToTaggedSigned:
+ state = LowerCheckedUint32ToTaggedSigned(node, frame_state, *effect,
+ *control);
+ break;
case IrOpcode::kCheckedFloat64ToInt32:
state = LowerCheckedFloat64ToInt32(node, frame_state, *effect, *control);
break;
@@ -677,6 +684,10 @@
case IrOpcode::kCheckedTaggedToFloat64:
state = LowerCheckedTaggedToFloat64(node, frame_state, *effect, *control);
break;
+ case IrOpcode::kCheckedTaggedToTaggedSigned:
+ state = LowerCheckedTaggedToTaggedSigned(node, frame_state, *effect,
+ *control);
+ break;
case IrOpcode::kTruncateTaggedToWord32:
state = LowerTruncateTaggedToWord32(node, *effect, *control);
break;
@@ -702,12 +713,27 @@
case IrOpcode::kObjectIsUndetectable:
state = LowerObjectIsUndetectable(node, *effect, *control);
break;
+ case IrOpcode::kArrayBufferWasNeutered:
+ state = LowerArrayBufferWasNeutered(node, *effect, *control);
+ break;
case IrOpcode::kStringFromCharCode:
state = LowerStringFromCharCode(node, *effect, *control);
break;
+ case IrOpcode::kStringFromCodePoint:
+ state = LowerStringFromCodePoint(node, *effect, *control);
+ break;
case IrOpcode::kStringCharCodeAt:
state = LowerStringCharCodeAt(node, *effect, *control);
break;
+ case IrOpcode::kStringEqual:
+ state = LowerStringEqual(node, *effect, *control);
+ break;
+ case IrOpcode::kStringLessThan:
+ state = LowerStringLessThan(node, *effect, *control);
+ break;
+ case IrOpcode::kStringLessThanOrEqual:
+ state = LowerStringLessThanOrEqual(node, *effect, *control);
+ break;
case IrOpcode::kCheckFloat64Hole:
state = LowerCheckFloat64Hole(node, frame_state, *effect, *control);
break;
@@ -762,75 +788,8 @@
EffectControlLinearizer::ValueEffectControl
EffectControlLinearizer::LowerChangeFloat64ToTagged(Node* node, Node* effect,
Node* control) {
- CheckForMinusZeroMode mode = CheckMinusZeroModeOf(node->op());
Node* value = node->InputAt(0);
-
- Node* value32 = graph()->NewNode(machine()->RoundFloat64ToInt32(), value);
- Node* check_same = graph()->NewNode(
- machine()->Float64Equal(), value,
- graph()->NewNode(machine()->ChangeInt32ToFloat64(), value32));
- Node* branch_same = graph()->NewNode(common()->Branch(), check_same, control);
-
- Node* if_smi = graph()->NewNode(common()->IfTrue(), branch_same);
- Node* vsmi;
- Node* if_box = graph()->NewNode(common()->IfFalse(), branch_same);
-
- if (mode == CheckForMinusZeroMode::kCheckForMinusZero) {
- // Check if {value} is -0.
- Node* check_zero = graph()->NewNode(machine()->Word32Equal(), value32,
- jsgraph()->Int32Constant(0));
- Node* branch_zero = graph()->NewNode(common()->Branch(BranchHint::kFalse),
- check_zero, if_smi);
-
- Node* if_zero = graph()->NewNode(common()->IfTrue(), branch_zero);
- Node* if_notzero = graph()->NewNode(common()->IfFalse(), branch_zero);
-
- // In case of 0, we need to check the high bits for the IEEE -0 pattern.
- Node* check_negative = graph()->NewNode(
- machine()->Int32LessThan(),
- graph()->NewNode(machine()->Float64ExtractHighWord32(), value),
- jsgraph()->Int32Constant(0));
- Node* branch_negative = graph()->NewNode(
- common()->Branch(BranchHint::kFalse), check_negative, if_zero);
-
- Node* if_negative = graph()->NewNode(common()->IfTrue(), branch_negative);
- Node* if_notnegative =
- graph()->NewNode(common()->IfFalse(), branch_negative);
-
- // We need to create a box for negative 0.
- if_smi = graph()->NewNode(common()->Merge(2), if_notzero, if_notnegative);
- if_box = graph()->NewNode(common()->Merge(2), if_box, if_negative);
- }
-
- // On 64-bit machines we can just wrap the 32-bit integer in a smi, for 32-bit
- // machines we need to deal with potential overflow and fallback to boxing.
- if (machine()->Is64()) {
- vsmi = ChangeInt32ToSmi(value32);
- } else {
- Node* smi_tag = graph()->NewNode(machine()->Int32AddWithOverflow(), value32,
- value32, if_smi);
-
- Node* check_ovf =
- graph()->NewNode(common()->Projection(1), smi_tag, if_smi);
- Node* branch_ovf = graph()->NewNode(common()->Branch(BranchHint::kFalse),
- check_ovf, if_smi);
-
- Node* if_ovf = graph()->NewNode(common()->IfTrue(), branch_ovf);
- if_box = graph()->NewNode(common()->Merge(2), if_ovf, if_box);
-
- if_smi = graph()->NewNode(common()->IfFalse(), branch_ovf);
- vsmi = graph()->NewNode(common()->Projection(0), smi_tag, if_smi);
- }
-
- // Allocate the box for the {value}.
- ValueEffectControl box = AllocateHeapNumberWithValue(value, effect, if_box);
-
- control = graph()->NewNode(common()->Merge(2), if_smi, box.control);
- value = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
- vsmi, box.value, control);
- effect =
- graph()->NewNode(common()->EffectPhi(2), effect, box.effect, control);
- return ValueEffectControl(value, effect, control);
+ return AllocateHeapNumberWithValue(value, effect, control);
}
EffectControlLinearizer::ValueEffectControl
@@ -939,6 +898,157 @@
}
EffectControlLinearizer::ValueEffectControl
+EffectControlLinearizer::LowerTruncateTaggedToBit(Node* node, Node* effect,
+ Node* control) {
+ Node* value = node->InputAt(0);
+ Node* one = jsgraph()->Int32Constant(1);
+ Node* zero = jsgraph()->Int32Constant(0);
+ Node* fzero = jsgraph()->Float64Constant(0.0);
+
+ // Collect effect/control/value triples.
+ int count = 0;
+ Node* values[7];
+ Node* effects[7];
+ Node* controls[6];
+
+ // Check if {value} is a Smi.
+ Node* check_smi = ObjectIsSmi(value);
+ Node* branch_smi = graph()->NewNode(common()->Branch(BranchHint::kFalse),
+ check_smi, control);
+
+ // If {value} is a Smi, then we only need to check that it's not zero.
+ Node* if_smi = graph()->NewNode(common()->IfTrue(), branch_smi);
+ Node* esmi = effect;
+ {
+ controls[count] = if_smi;
+ effects[count] = esmi;
+ values[count] =
+ graph()->NewNode(machine()->Word32Equal(),
+ graph()->NewNode(machine()->WordEqual(), value,
+ jsgraph()->ZeroConstant()),
+ zero);
+ count++;
+ }
+ control = graph()->NewNode(common()->IfFalse(), branch_smi);
+
+ // Load the map instance type of {value}.
+ 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);
+
+ // Check if {value} is an Oddball.
+ Node* check_oddball =
+ graph()->NewNode(machine()->Word32Equal(), value_instance_type,
+ jsgraph()->Int32Constant(ODDBALL_TYPE));
+ Node* branch_oddball = graph()->NewNode(common()->Branch(BranchHint::kTrue),
+ check_oddball, control);
+
+ // The only Oddball {value} that is trueish is true itself.
+ Node* if_oddball = graph()->NewNode(common()->IfTrue(), branch_oddball);
+ Node* eoddball = effect;
+ {
+ controls[count] = if_oddball;
+ effects[count] = eoddball;
+ values[count] = graph()->NewNode(machine()->WordEqual(), value,
+ jsgraph()->TrueConstant());
+ count++;
+ }
+ control = graph()->NewNode(common()->IfFalse(), branch_oddball);
+
+ // Check if {value} is a String.
+ Node* check_string =
+ graph()->NewNode(machine()->Int32LessThan(), value_instance_type,
+ jsgraph()->Int32Constant(FIRST_NONSTRING_TYPE));
+ Node* branch_string =
+ graph()->NewNode(common()->Branch(), check_string, control);
+
+ // For String {value}, we need to check that the length is not zero.
+ Node* if_string = graph()->NewNode(common()->IfTrue(), branch_string);
+ Node* estring = effect;
+ {
+ // Load the {value} length.
+ Node* value_length = estring = graph()->NewNode(
+ simplified()->LoadField(AccessBuilder::ForStringLength()), value,
+ estring, if_string);
+
+ controls[count] = if_string;
+ effects[count] = estring;
+ values[count] =
+ graph()->NewNode(machine()->Word32Equal(),
+ graph()->NewNode(machine()->WordEqual(), value_length,
+ jsgraph()->ZeroConstant()),
+ zero);
+ count++;
+ }
+ control = graph()->NewNode(common()->IfFalse(), branch_string);
+
+ // Check if {value} is a HeapNumber.
+ Node* check_heapnumber =
+ graph()->NewNode(machine()->Word32Equal(), value_instance_type,
+ jsgraph()->Int32Constant(HEAP_NUMBER_TYPE));
+ Node* branch_heapnumber =
+ graph()->NewNode(common()->Branch(), check_heapnumber, control);
+
+ // For HeapNumber {value}, just check that its value is not 0.0, -0.0 or NaN.
+ Node* if_heapnumber = graph()->NewNode(common()->IfTrue(), branch_heapnumber);
+ Node* eheapnumber = effect;
+ {
+ // Load the raw value of {value}.
+ Node* value_value = eheapnumber = graph()->NewNode(
+ simplified()->LoadField(AccessBuilder::ForHeapNumberValue()), value,
+ eheapnumber, if_heapnumber);
+
+ // Check if {value} is either less than 0.0 or greater than 0.0.
+ Node* check =
+ graph()->NewNode(machine()->Float64LessThan(), fzero, value_value);
+ Node* branch = graph()->NewNode(common()->Branch(), check, if_heapnumber);
+
+ controls[count] = graph()->NewNode(common()->IfTrue(), branch);
+ effects[count] = eheapnumber;
+ values[count] = one;
+ count++;
+
+ controls[count] = graph()->NewNode(common()->IfFalse(), branch);
+ effects[count] = eheapnumber;
+ values[count] =
+ graph()->NewNode(machine()->Float64LessThan(), value_value, fzero);
+ count++;
+ }
+ control = graph()->NewNode(common()->IfFalse(), branch_heapnumber);
+
+ // The {value} is either a JSReceiver, a Symbol or some Simd128Value. In
+ // those cases we can just the undetectable bit on the map, which will only
+ // be set for certain JSReceivers, i.e. document.all.
+ {
+ // Load the {value} map bit field.
+ Node* value_map_bitfield = effect = graph()->NewNode(
+ simplified()->LoadField(AccessBuilder::ForMapBitField()), value_map,
+ effect, control);
+
+ controls[count] = control;
+ effects[count] = effect;
+ values[count] = graph()->NewNode(
+ machine()->Word32Equal(),
+ graph()->NewNode(machine()->Word32And(), value_map_bitfield,
+ jsgraph()->Int32Constant(1 << Map::kIsUndetectable)),
+ zero);
+ count++;
+ }
+
+ // Merge the different controls.
+ control = graph()->NewNode(common()->Merge(count), count, controls);
+ effects[count] = control;
+ effect = graph()->NewNode(common()->EffectPhi(count), count + 1, effects);
+ values[count] = control;
+ value = graph()->NewNode(common()->Phi(MachineRepresentation::kBit, count),
+ count + 1, values);
+
+ return ValueEffectControl(value, effect, control);
+}
+
+EffectControlLinearizer::ValueEffectControl
EffectControlLinearizer::LowerChangeTaggedToInt32(Node* node, Node* effect,
Node* control) {
Node* value = node->InputAt(0);
@@ -1164,8 +1274,8 @@
}
EffectControlLinearizer::ValueEffectControl
-EffectControlLinearizer::LowerCheckTaggedPointer(Node* node, Node* frame_state,
- Node* effect, Node* control) {
+EffectControlLinearizer::LowerCheckHeapObject(Node* node, Node* frame_state,
+ Node* effect, Node* control) {
Node* value = node->InputAt(0);
Node* check = ObjectIsSmi(value);
@@ -1177,19 +1287,6 @@
}
EffectControlLinearizer::ValueEffectControl
-EffectControlLinearizer::LowerCheckTaggedSigned(Node* node, Node* frame_state,
- Node* effect, Node* control) {
- Node* value = node->InputAt(0);
-
- Node* check = ObjectIsSmi(value);
- control = effect =
- graph()->NewNode(common()->DeoptimizeUnless(DeoptimizeReason::kNotASmi),
- check, frame_state, effect, control);
-
- return ValueEffectControl(value, effect, control);
-}
-
-EffectControlLinearizer::ValueEffectControl
EffectControlLinearizer::LowerCheckedInt32Add(Node* node, Node* frame_state,
Node* effect, Node* control) {
Node* lhs = node->InputAt(0);
@@ -1515,6 +1612,27 @@
}
EffectControlLinearizer::ValueEffectControl
+EffectControlLinearizer::LowerCheckedInt32ToTaggedSigned(Node* node,
+ Node* frame_state,
+ Node* effect,
+ Node* control) {
+ DCHECK(SmiValuesAre31Bits());
+ Node* value = node->InputAt(0);
+
+ Node* add = graph()->NewNode(machine()->Int32AddWithOverflow(), value, value,
+ control);
+
+ Node* check = graph()->NewNode(common()->Projection(1), add, control);
+ control = effect =
+ graph()->NewNode(common()->DeoptimizeIf(DeoptimizeReason::kOverflow),
+ check, frame_state, effect, control);
+
+ value = graph()->NewNode(common()->Projection(0), add, control);
+
+ return ValueEffectControl(value, effect, control);
+}
+
+EffectControlLinearizer::ValueEffectControl
EffectControlLinearizer::LowerCheckedUint32ToInt32(Node* node,
Node* frame_state,
Node* effect,
@@ -1531,6 +1649,22 @@
}
EffectControlLinearizer::ValueEffectControl
+EffectControlLinearizer::LowerCheckedUint32ToTaggedSigned(Node* node,
+ Node* frame_state,
+ Node* effect,
+ Node* control) {
+ Node* value = node->InputAt(0);
+ Node* check = graph()->NewNode(machine()->Uint32LessThanOrEqual(), value,
+ SmiMaxValueConstant());
+ control = effect = graph()->NewNode(
+ common()->DeoptimizeUnless(DeoptimizeReason::kLostPrecision), check,
+ frame_state, effect, control);
+ value = ChangeUint32ToSmi(value);
+
+ return ValueEffectControl(value, effect, control);
+}
+
+EffectControlLinearizer::ValueEffectControl
EffectControlLinearizer::BuildCheckedFloat64ToInt32(CheckForMinusZeroMode mode,
Node* value,
Node* frame_state,
@@ -1667,8 +1801,8 @@
break;
}
case CheckTaggedInputMode::kNumberOrOddball: {
- Node* branch = graph()->NewNode(common()->Branch(BranchHint::kTrue),
- check_number, control);
+ Node* branch =
+ graph()->NewNode(common()->Branch(), check_number, control);
Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
Node* etrue = effect;
@@ -1710,8 +1844,7 @@
Node* value = node->InputAt(0);
Node* check = ObjectIsSmi(value);
- Node* branch =
- graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
+ Node* branch = graph()->NewNode(common()->Branch(), check, control);
// In the Smi case, just convert to int32 and then float64.
Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
@@ -1736,6 +1869,21 @@
}
EffectControlLinearizer::ValueEffectControl
+EffectControlLinearizer::LowerCheckedTaggedToTaggedSigned(Node* node,
+ Node* frame_state,
+ Node* effect,
+ Node* control) {
+ Node* value = node->InputAt(0);
+
+ Node* check = ObjectIsSmi(value);
+ control = effect =
+ graph()->NewNode(common()->DeoptimizeUnless(DeoptimizeReason::kNotASmi),
+ check, frame_state, effect, control);
+
+ return ValueEffectControl(value, effect, control);
+}
+
+EffectControlLinearizer::ValueEffectControl
EffectControlLinearizer::LowerTruncateTaggedToWord32(Node* node, Node* effect,
Node* control) {
Node* value = node->InputAt(0);
@@ -1996,6 +2144,26 @@
}
EffectControlLinearizer::ValueEffectControl
+EffectControlLinearizer::LowerArrayBufferWasNeutered(Node* node, Node* effect,
+ Node* control) {
+ Node* value = node->InputAt(0);
+
+ Node* value_bit_field = effect = graph()->NewNode(
+ simplified()->LoadField(AccessBuilder::ForJSArrayBufferBitField()), value,
+ effect, control);
+ value = graph()->NewNode(
+ machine()->Word32Equal(),
+ graph()->NewNode(machine()->Word32Equal(),
+ graph()->NewNode(machine()->Word32And(), value_bit_field,
+ jsgraph()->Int32Constant(
+ JSArrayBuffer::WasNeutered::kMask)),
+ jsgraph()->Int32Constant(0)),
+ jsgraph()->Int32Constant(0));
+
+ return ValueEffectControl(value, effect, control);
+}
+
+EffectControlLinearizer::ValueEffectControl
EffectControlLinearizer::LowerStringCharCodeAt(Node* node, Node* effect,
Node* control) {
Node* subject = node->InputAt(0);
@@ -2382,6 +2550,236 @@
}
EffectControlLinearizer::ValueEffectControl
+EffectControlLinearizer::LowerStringFromCodePoint(Node* node, Node* effect,
+ Node* control) {
+ Node* value = node->InputAt(0);
+ Node* code = value;
+
+ Node* etrue0 = effect;
+ Node* vtrue0;
+
+ // Check if the {code} is a single code unit
+ Node* check0 = graph()->NewNode(machine()->Uint32LessThanOrEqual(), code,
+ jsgraph()->Uint32Constant(0xFFFF));
+ Node* branch0 =
+ graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control);
+
+ Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
+ {
+ // Check if the {code} is a one byte character
+ Node* check1 = graph()->NewNode(
+ machine()->Uint32LessThanOrEqual(), code,
+ jsgraph()->Uint32Constant(String::kMaxOneByteCharCode));
+ Node* branch1 =
+ graph()->NewNode(common()->Branch(BranchHint::kTrue), check1, if_true0);
+
+ Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
+ Node* etrue1 = etrue0;
+ Node* vtrue1;
+ {
+ // Load the isolate wide single character string cache.
+ Node* cache =
+ jsgraph()->HeapConstant(factory()->single_character_string_cache());
+
+ // Compute the {cache} index for {code}.
+ Node* index =
+ machine()->Is32()
+ ? code
+ : graph()->NewNode(machine()->ChangeUint32ToUint64(), code);
+
+ // Check if we have an entry for the {code} in the single character string
+ // cache already.
+ Node* entry = etrue1 = graph()->NewNode(
+ simplified()->LoadElement(AccessBuilder::ForFixedArrayElement()),
+ cache, index, etrue1, if_true1);
+
+ Node* check2 = graph()->NewNode(machine()->WordEqual(), entry,
+ jsgraph()->UndefinedConstant());
+ Node* branch2 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
+ check2, if_true1);
+
+ Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2);
+ Node* etrue2 = etrue1;
+ Node* vtrue2;
+ {
+ // Allocate a new SeqOneByteString for {code}.
+ vtrue2 = etrue2 = graph()->NewNode(
+ simplified()->Allocate(NOT_TENURED),
+ jsgraph()->Int32Constant(SeqOneByteString::SizeFor(1)), etrue2,
+ if_true2);
+ etrue2 = graph()->NewNode(
+ simplified()->StoreField(AccessBuilder::ForMap()), vtrue2,
+ jsgraph()->HeapConstant(factory()->one_byte_string_map()), etrue2,
+ if_true2);
+ etrue2 = graph()->NewNode(
+ simplified()->StoreField(AccessBuilder::ForNameHashField()), vtrue2,
+ jsgraph()->IntPtrConstant(Name::kEmptyHashField), etrue2, if_true2);
+ etrue2 = graph()->NewNode(
+ simplified()->StoreField(AccessBuilder::ForStringLength()), vtrue2,
+ jsgraph()->SmiConstant(1), etrue2, if_true2);
+ etrue2 = graph()->NewNode(
+ machine()->Store(StoreRepresentation(MachineRepresentation::kWord8,
+ kNoWriteBarrier)),
+ vtrue2, jsgraph()->IntPtrConstant(SeqOneByteString::kHeaderSize -
+ kHeapObjectTag),
+ code, etrue2, if_true2);
+
+ // Remember it in the {cache}.
+ etrue2 = graph()->NewNode(
+ simplified()->StoreElement(AccessBuilder::ForFixedArrayElement()),
+ cache, index, vtrue2, etrue2, if_true2);
+ }
+
+ // Use the {entry} from the {cache}.
+ Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2);
+ Node* efalse2 = etrue0;
+ Node* vfalse2 = entry;
+
+ if_true1 = graph()->NewNode(common()->Merge(2), if_true2, if_false2);
+ etrue1 =
+ graph()->NewNode(common()->EffectPhi(2), etrue2, efalse2, if_true1);
+ vtrue1 =
+ graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
+ vtrue2, vfalse2, if_true1);
+ }
+
+ Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
+ Node* efalse1 = effect;
+ Node* vfalse1;
+ {
+ // Allocate a new SeqTwoByteString for {code}.
+ vfalse1 = efalse1 = graph()->NewNode(
+ simplified()->Allocate(NOT_TENURED),
+ jsgraph()->Int32Constant(SeqTwoByteString::SizeFor(1)), efalse1,
+ if_false1);
+ efalse1 = graph()->NewNode(
+ simplified()->StoreField(AccessBuilder::ForMap()), vfalse1,
+ jsgraph()->HeapConstant(factory()->string_map()), efalse1, if_false1);
+ efalse1 = graph()->NewNode(
+ simplified()->StoreField(AccessBuilder::ForNameHashField()), vfalse1,
+ jsgraph()->IntPtrConstant(Name::kEmptyHashField), efalse1, if_false1);
+ efalse1 = graph()->NewNode(
+ simplified()->StoreField(AccessBuilder::ForStringLength()), vfalse1,
+ jsgraph()->SmiConstant(1), efalse1, if_false1);
+ efalse1 = graph()->NewNode(
+ machine()->Store(StoreRepresentation(MachineRepresentation::kWord16,
+ kNoWriteBarrier)),
+ vfalse1, jsgraph()->IntPtrConstant(SeqTwoByteString::kHeaderSize -
+ kHeapObjectTag),
+ code, efalse1, if_false1);
+ }
+
+ if_true0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
+ etrue0 =
+ graph()->NewNode(common()->EffectPhi(2), etrue1, efalse1, if_true0);
+ vtrue0 = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
+ vtrue1, vfalse1, if_true0);
+ }
+
+ // Generate surrogate pair string
+ Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
+ Node* efalse0 = effect;
+ Node* vfalse0;
+ {
+ switch (UnicodeEncodingOf(node->op())) {
+ case UnicodeEncoding::UTF16:
+ break;
+
+ case UnicodeEncoding::UTF32: {
+ // Convert UTF32 to UTF16 code units, and store as a 32 bit word.
+ Node* lead_offset = jsgraph()->Int32Constant(0xD800 - (0x10000 >> 10));
+
+ // lead = (codepoint >> 10) + LEAD_OFFSET
+ Node* lead =
+ graph()->NewNode(machine()->Int32Add(),
+ graph()->NewNode(machine()->Word32Shr(), code,
+ jsgraph()->Int32Constant(10)),
+ lead_offset);
+
+ // trail = (codepoint & 0x3FF) + 0xDC00;
+ Node* trail =
+ graph()->NewNode(machine()->Int32Add(),
+ graph()->NewNode(machine()->Word32And(), code,
+ jsgraph()->Int32Constant(0x3FF)),
+ jsgraph()->Int32Constant(0xDC00));
+
+ // codpoint = (trail << 16) | lead;
+ code = graph()->NewNode(machine()->Word32Or(),
+ graph()->NewNode(machine()->Word32Shl(), trail,
+ jsgraph()->Int32Constant(16)),
+ lead);
+ break;
+ }
+ }
+
+ // Allocate a new SeqTwoByteString for {code}.
+ vfalse0 = efalse0 =
+ graph()->NewNode(simplified()->Allocate(NOT_TENURED),
+ jsgraph()->Int32Constant(SeqTwoByteString::SizeFor(2)),
+ efalse0, if_false0);
+ efalse0 = graph()->NewNode(
+ simplified()->StoreField(AccessBuilder::ForMap()), vfalse0,
+ jsgraph()->HeapConstant(factory()->string_map()), efalse0, if_false0);
+ efalse0 = graph()->NewNode(
+ simplified()->StoreField(AccessBuilder::ForNameHashField()), vfalse0,
+ jsgraph()->IntPtrConstant(Name::kEmptyHashField), efalse0, if_false0);
+ efalse0 = graph()->NewNode(
+ simplified()->StoreField(AccessBuilder::ForStringLength()), vfalse0,
+ jsgraph()->SmiConstant(2), efalse0, if_false0);
+ efalse0 = graph()->NewNode(
+ machine()->Store(StoreRepresentation(MachineRepresentation::kWord32,
+ kNoWriteBarrier)),
+ vfalse0, jsgraph()->IntPtrConstant(SeqTwoByteString::kHeaderSize -
+ kHeapObjectTag),
+ code, efalse0, if_false0);
+ }
+
+ control = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
+ effect = graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control);
+ value = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
+ vtrue0, vfalse0, control);
+
+ return ValueEffectControl(value, effect, control);
+}
+
+EffectControlLinearizer::ValueEffectControl
+EffectControlLinearizer::LowerStringComparison(Callable const& callable,
+ Node* node, Node* effect,
+ Node* control) {
+ Operator::Properties properties = Operator::kEliminatable;
+ CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
+ CallDescriptor* desc = Linkage::GetStubCallDescriptor(
+ isolate(), graph()->zone(), callable.descriptor(), 0, flags, properties);
+ node->InsertInput(graph()->zone(), 0,
+ jsgraph()->HeapConstant(callable.code()));
+ node->AppendInput(graph()->zone(), jsgraph()->NoContextConstant());
+ node->AppendInput(graph()->zone(), effect);
+ NodeProperties::ChangeOp(node, common()->Call(desc));
+ return ValueEffectControl(node, node, control);
+}
+
+EffectControlLinearizer::ValueEffectControl
+EffectControlLinearizer::LowerStringEqual(Node* node, Node* effect,
+ Node* control) {
+ return LowerStringComparison(CodeFactory::StringEqual(isolate()), node,
+ effect, control);
+}
+
+EffectControlLinearizer::ValueEffectControl
+EffectControlLinearizer::LowerStringLessThan(Node* node, Node* effect,
+ Node* control) {
+ return LowerStringComparison(CodeFactory::StringLessThan(isolate()), node,
+ effect, control);
+}
+
+EffectControlLinearizer::ValueEffectControl
+EffectControlLinearizer::LowerStringLessThanOrEqual(Node* node, Node* effect,
+ Node* control) {
+ return LowerStringComparison(CodeFactory::StringLessThanOrEqual(isolate()),
+ node, effect, control);
+}
+
+EffectControlLinearizer::ValueEffectControl
EffectControlLinearizer::LowerCheckFloat64Hole(Node* node, Node* frame_state,
Node* effect, Node* control) {
// If we reach this point w/o eliminating the {node} that's marked