diff options
Diffstat (limited to 'deps/v8/src/compiler/effect-control-linearizer.cc')
-rw-r--r-- | deps/v8/src/compiler/effect-control-linearizer.cc | 549 |
1 files changed, 398 insertions, 151 deletions
diff --git a/deps/v8/src/compiler/effect-control-linearizer.cc b/deps/v8/src/compiler/effect-control-linearizer.cc index 4bb4f8df77..97f78418d0 100644 --- a/deps/v8/src/compiler/effect-control-linearizer.cc +++ b/deps/v8/src/compiler/effect-control-linearizer.cc @@ -628,9 +628,15 @@ bool EffectControlLinearizer::TryWireInStateEffect(Node* node, case IrOpcode::kChangeInt32ToTagged: result = LowerChangeInt32ToTagged(node); break; + case IrOpcode::kChangeInt64ToTagged: + result = LowerChangeInt64ToTagged(node); + break; case IrOpcode::kChangeUint32ToTagged: result = LowerChangeUint32ToTagged(node); break; + case IrOpcode::kChangeUint64ToTagged: + result = LowerChangeUint64ToTagged(node); + break; case IrOpcode::kChangeFloat64ToTagged: result = LowerChangeFloat64ToTagged(node); break; @@ -640,6 +646,9 @@ bool EffectControlLinearizer::TryWireInStateEffect(Node* node, case IrOpcode::kChangeTaggedSignedToInt32: result = LowerChangeTaggedSignedToInt32(node); break; + case IrOpcode::kChangeTaggedSignedToInt64: + result = LowerChangeTaggedSignedToInt64(node); + break; case IrOpcode::kChangeTaggedToBit: result = LowerChangeTaggedToBit(node); break; @@ -649,6 +658,9 @@ bool EffectControlLinearizer::TryWireInStateEffect(Node* node, case IrOpcode::kChangeTaggedToUint32: result = LowerChangeTaggedToUint32(node); break; + case IrOpcode::kChangeTaggedToInt64: + result = LowerChangeTaggedToInt64(node); + break; case IrOpcode::kChangeTaggedToFloat64: result = LowerChangeTaggedToFloat64(node); break; @@ -718,12 +730,24 @@ bool EffectControlLinearizer::TryWireInStateEffect(Node* node, case IrOpcode::kCheckedInt32ToTaggedSigned: result = LowerCheckedInt32ToTaggedSigned(node, frame_state); break; + case IrOpcode::kCheckedInt64ToInt32: + result = LowerCheckedInt64ToInt32(node, frame_state); + break; + case IrOpcode::kCheckedInt64ToTaggedSigned: + result = LowerCheckedInt64ToTaggedSigned(node, frame_state); + break; case IrOpcode::kCheckedUint32ToInt32: result = LowerCheckedUint32ToInt32(node, frame_state); break; case IrOpcode::kCheckedUint32ToTaggedSigned: result = LowerCheckedUint32ToTaggedSigned(node, frame_state); break; + case IrOpcode::kCheckedUint64ToInt32: + result = LowerCheckedUint64ToInt32(node, frame_state); + break; + case IrOpcode::kCheckedUint64ToTaggedSigned: + result = LowerCheckedUint64ToTaggedSigned(node, frame_state); + break; case IrOpcode::kCheckedFloat64ToInt32: result = LowerCheckedFloat64ToInt32(node, frame_state); break; @@ -824,15 +848,15 @@ bool EffectControlLinearizer::TryWireInStateEffect(Node* node, case IrOpcode::kNewConsString: result = LowerNewConsString(node); break; - case IrOpcode::kArrayBufferWasNeutered: - result = LowerArrayBufferWasNeutered(node); - break; case IrOpcode::kSameValue: result = LowerSameValue(node); break; case IrOpcode::kDeadValue: result = LowerDeadValue(node); break; + case IrOpcode::kStringConcat: + result = LowerStringConcat(node); + break; case IrOpcode::kStringFromSingleCharCode: result = LowerStringFromSingleCharCode(node); break; @@ -1120,6 +1144,35 @@ Node* EffectControlLinearizer::LowerChangeInt32ToTagged(Node* node) { return done.PhiAt(0); } +Node* EffectControlLinearizer::LowerChangeInt64ToTagged(Node* node) { + Node* value = node->InputAt(0); + + auto if_not_in_smi_range = __ MakeDeferredLabel(); + auto done = __ MakeLabel(MachineRepresentation::kTagged); + + Node* value32 = __ TruncateInt64ToInt32(value); + __ GotoIfNot(__ Word64Equal(__ ChangeInt32ToInt64(value32), value), + &if_not_in_smi_range); + + if (SmiValuesAre32Bits()) { + Node* value_smi = ChangeInt64ToSmi(value); + __ Goto(&done, value_smi); + } else { + Node* add = __ Int32AddWithOverflow(value32, value32); + Node* ovf = __ Projection(1, add); + __ GotoIf(ovf, &if_not_in_smi_range); + Node* value_smi = ChangeInt32ToIntPtr(__ Projection(0, add)); + __ Goto(&done, value_smi); + } + + __ Bind(&if_not_in_smi_range); + Node* number = AllocateHeapNumberWithValue(__ ChangeInt64ToFloat64(value)); + __ Goto(&done, number); + + __ Bind(&done); + return done.PhiAt(0); +} + Node* EffectControlLinearizer::LowerChangeUint32ToTagged(Node* node) { Node* value = node->InputAt(0); @@ -1139,11 +1192,36 @@ Node* EffectControlLinearizer::LowerChangeUint32ToTagged(Node* node) { return done.PhiAt(0); } +Node* EffectControlLinearizer::LowerChangeUint64ToTagged(Node* node) { + Node* value = node->InputAt(0); + + auto if_not_in_smi_range = __ MakeDeferredLabel(); + auto done = __ MakeLabel(MachineRepresentation::kTagged); + + Node* check = + __ Uint64LessThanOrEqual(value, __ Int64Constant(Smi::kMaxValue)); + __ GotoIfNot(check, &if_not_in_smi_range); + __ Goto(&done, ChangeInt64ToSmi(value)); + + __ Bind(&if_not_in_smi_range); + Node* number = AllocateHeapNumberWithValue(__ ChangeInt64ToFloat64(value)); + + __ Goto(&done, number); + __ Bind(&done); + + return done.PhiAt(0); +} + Node* EffectControlLinearizer::LowerChangeTaggedSignedToInt32(Node* node) { Node* value = node->InputAt(0); return ChangeSmiToInt32(value); } +Node* EffectControlLinearizer::LowerChangeTaggedSignedToInt64(Node* node) { + Node* value = node->InputAt(0); + return ChangeSmiToInt64(value); +} + Node* EffectControlLinearizer::LowerChangeTaggedToBit(Node* node) { Node* value = node->InputAt(0); return __ WordEqual(value, __ TrueConstant()); @@ -1280,6 +1358,26 @@ Node* EffectControlLinearizer::LowerChangeTaggedToUint32(Node* node) { return done.PhiAt(0); } +Node* EffectControlLinearizer::LowerChangeTaggedToInt64(Node* node) { + Node* value = node->InputAt(0); + + auto if_not_smi = __ MakeDeferredLabel(); + auto done = __ MakeLabel(MachineRepresentation::kWord64); + + Node* check = ObjectIsSmi(value); + __ GotoIfNot(check, &if_not_smi); + __ Goto(&done, ChangeSmiToInt64(value)); + + __ Bind(&if_not_smi); + STATIC_ASSERT(HeapNumber::kValueOffset == Oddball::kToNumberRawOffset); + Node* vfalse = __ LoadField(AccessBuilder::ForHeapNumberValue(), value); + vfalse = __ ChangeFloat64ToInt64(vfalse); + __ Goto(&done, vfalse); + + __ Bind(&done); + return done.PhiAt(0); +} + Node* EffectControlLinearizer::LowerChangeTaggedToFloat64(Node* node) { return LowerTruncateTaggedToFloat64(node); } @@ -1353,7 +1451,7 @@ void EffectControlLinearizer::LowerCheckMaps(Node* node, Node* frame_state) { size_t const map_count = maps.size(); if (p.flags() & CheckMapsFlag::kTryMigrateInstance) { - auto done = __ MakeDeferredLabel(); + auto done = __ MakeLabel(); auto migrate = __ MakeDeferredLabel(); // Load the current map of the {value}. @@ -1364,10 +1462,11 @@ void EffectControlLinearizer::LowerCheckMaps(Node* node, Node* frame_state) { Node* map = __ HeapConstant(maps[i]); Node* check = __ WordEqual(value_map, map); if (i == map_count - 1) { - __ GotoIfNot(check, &migrate); - __ Goto(&done); + __ Branch(check, &done, &migrate, IsSafetyCheck::kCriticalSafetyCheck); } else { - __ GotoIf(check, &done); + auto next_map = __ MakeLabel(); + __ Branch(check, &done, &next_map, IsSafetyCheck::kCriticalSafetyCheck); + __ Bind(&next_map); } } @@ -1382,7 +1481,8 @@ void EffectControlLinearizer::LowerCheckMaps(Node* node, Node* frame_state) { __ Int32Constant(Map::IsDeprecatedBit::kMask)), __ Int32Constant(0)); __ DeoptimizeIf(DeoptimizeReason::kWrongMap, p.feedback(), - if_not_deprecated, frame_state); + if_not_deprecated, frame_state, + IsSafetyCheck::kCriticalSafetyCheck); Operator::Properties properties = Operator::kNoDeopt | Operator::kNoThrow; Runtime::FunctionId id = Runtime::kTryMigrateInstance; @@ -1393,7 +1493,7 @@ void EffectControlLinearizer::LowerCheckMaps(Node* node, Node* frame_state) { __ Int32Constant(1), __ NoContextConstant()); Node* check = ObjectIsSmi(result); __ DeoptimizeIf(DeoptimizeReason::kInstanceMigrationFailed, p.feedback(), - check, frame_state); + check, frame_state, IsSafetyCheck::kCriticalSafetyCheck); } // Reload the current map of the {value}. @@ -1405,9 +1505,11 @@ void EffectControlLinearizer::LowerCheckMaps(Node* node, Node* frame_state) { Node* check = __ WordEqual(value_map, map); if (i == map_count - 1) { __ DeoptimizeIfNot(DeoptimizeReason::kWrongMap, p.feedback(), check, - frame_state); + frame_state, IsSafetyCheck::kCriticalSafetyCheck); } else { - __ GotoIf(check, &done); + auto next_map = __ MakeLabel(); + __ Branch(check, &done, &next_map, IsSafetyCheck::kCriticalSafetyCheck); + __ Bind(&next_map); } } @@ -1424,9 +1526,11 @@ void EffectControlLinearizer::LowerCheckMaps(Node* node, Node* frame_state) { Node* check = __ WordEqual(value_map, map); if (i == map_count - 1) { __ DeoptimizeIfNot(DeoptimizeReason::kWrongMap, p.feedback(), check, - frame_state); + frame_state, IsSafetyCheck::kCriticalSafetyCheck); } else { - __ GotoIf(check, &done); + auto next_map = __ MakeLabel(); + __ Branch(check, &done, &next_map, IsSafetyCheck::kCriticalSafetyCheck); + __ Bind(&next_map); } } __ Goto(&done); @@ -1447,7 +1551,14 @@ Node* EffectControlLinearizer::LowerCompareMaps(Node* node) { for (size_t i = 0; i < map_count; ++i) { Node* map = __ HeapConstant(maps[i]); Node* check = __ WordEqual(value_map, map); - __ GotoIf(check, &done, __ Int32Constant(1)); + auto next_map = __ MakeLabel(); + auto passed = __ MakeLabel(); + __ Branch(check, &passed, &next_map, IsSafetyCheck::kCriticalSafetyCheck); + + __ Bind(&passed); + __ Goto(&done, __ Int32Constant(1)); + + __ Bind(&next_map); } __ Goto(&done, __ Int32Constant(0)); @@ -1544,6 +1655,24 @@ void EffectControlLinearizer::LowerCheckIf(Node* node, Node* frame_state) { __ DeoptimizeIfNot(p.reason(), p.feedback(), value, frame_state); } +Node* EffectControlLinearizer::LowerStringConcat(Node* node) { + Node* lhs = node->InputAt(1); + Node* rhs = node->InputAt(2); + + Callable const callable = + CodeFactory::StringAdd(isolate(), STRING_ADD_CHECK_NONE); + auto call_descriptor = Linkage::GetStubCallDescriptor( + graph()->zone(), callable.descriptor(), + callable.descriptor().GetStackParameterCount(), CallDescriptor::kNoFlags, + Operator::kNoDeopt | Operator::kNoWrite | Operator::kNoThrow); + + Node* value = + __ Call(call_descriptor, jsgraph()->HeapConstant(callable.code()), lhs, + rhs, __ NoContextConstant()); + + return value; +} + Node* EffectControlLinearizer::LowerCheckedInt32Add(Node* node, Node* frame_state) { Node* lhs = node->InputAt(0); @@ -1572,63 +1701,87 @@ Node* EffectControlLinearizer::LowerCheckedInt32Div(Node* node, Node* frame_state) { Node* lhs = node->InputAt(0); Node* rhs = node->InputAt(1); - - auto if_not_positive = __ MakeDeferredLabel(); - auto if_is_minint = __ MakeDeferredLabel(); - auto done = __ MakeLabel(MachineRepresentation::kWord32); - auto minint_check_done = __ MakeLabel(); - Node* zero = __ Int32Constant(0); - // Check if {rhs} is positive (and not zero). - Node* check0 = __ Int32LessThan(zero, rhs); - __ GotoIfNot(check0, &if_not_positive); + // Check if the {rhs} is a known power of two. + Int32Matcher m(rhs); + if (m.IsPowerOf2()) { + // Since we know that {rhs} is a power of two, we can perform a fast + // check to see if the relevant least significant bits of the {lhs} + // are all zero, and if so we know that we can perform a division + // safely (and fast by doing an arithmetic - aka sign preserving - + // right shift on {lhs}). + int32_t divisor = m.Value(); + Node* mask = __ Int32Constant(divisor - 1); + Node* shift = __ Int32Constant(WhichPowerOf2(divisor)); + Node* check = __ Word32Equal(__ Word32And(lhs, mask), zero); + __ DeoptimizeIfNot(DeoptimizeReason::kLostPrecision, VectorSlotPair(), + check, frame_state); + return __ Word32Sar(lhs, shift); + } else { + auto if_rhs_positive = __ MakeLabel(); + auto if_rhs_negative = __ MakeDeferredLabel(); + auto done = __ MakeLabel(MachineRepresentation::kWord32); - // Fast case, no additional checking required. - __ Goto(&done, __ Int32Div(lhs, rhs)); + // Check if {rhs} is positive (and not zero). + Node* check_rhs_positive = __ Int32LessThan(zero, rhs); + __ Branch(check_rhs_positive, &if_rhs_positive, &if_rhs_negative); - { - __ Bind(&if_not_positive); + __ Bind(&if_rhs_positive); + { + // Fast case, no additional checking required. + __ Goto(&done, __ Int32Div(lhs, rhs)); + } - // Check if {rhs} is zero. - Node* check = __ Word32Equal(rhs, zero); - __ DeoptimizeIf(DeoptimizeReason::kDivisionByZero, VectorSlotPair(), check, - frame_state); + __ Bind(&if_rhs_negative); + { + auto if_lhs_minint = __ MakeDeferredLabel(); + auto if_lhs_notminint = __ MakeLabel(); + + // Check if {rhs} is zero. + Node* check_rhs_zero = __ Word32Equal(rhs, zero); + __ DeoptimizeIf(DeoptimizeReason::kDivisionByZero, VectorSlotPair(), + check_rhs_zero, frame_state); + + // Check if {lhs} is zero, as that would produce minus zero. + Node* check_lhs_zero = __ Word32Equal(lhs, zero); + __ DeoptimizeIf(DeoptimizeReason::kMinusZero, VectorSlotPair(), + check_lhs_zero, frame_state); + + // Check if {lhs} is kMinInt and {rhs} is -1, in which case we'd have + // to return -kMinInt, which is not representable as Word32. + Node* check_lhs_minint = graph()->NewNode(machine()->Word32Equal(), lhs, + __ Int32Constant(kMinInt)); + __ Branch(check_lhs_minint, &if_lhs_minint, &if_lhs_notminint); + + __ Bind(&if_lhs_minint); + { + // Check that {rhs} is not -1, otherwise result would be -kMinInt. + Node* check_rhs_minusone = __ Word32Equal(rhs, __ Int32Constant(-1)); + __ DeoptimizeIf(DeoptimizeReason::kOverflow, VectorSlotPair(), + check_rhs_minusone, frame_state); - // Check if {lhs} is zero, as that would produce minus zero. - check = __ Word32Equal(lhs, zero); - __ DeoptimizeIf(DeoptimizeReason::kMinusZero, VectorSlotPair(), check, - frame_state); + // Perform the actual integer division. + __ Goto(&done, __ Int32Div(lhs, rhs)); + } - // Check if {lhs} is kMinInt and {rhs} is -1, in which case we'd have - // to return -kMinInt, which is not representable. - Node* minint = __ Int32Constant(std::numeric_limits<int32_t>::min()); - Node* check1 = graph()->NewNode(machine()->Word32Equal(), lhs, minint); - __ GotoIf(check1, &if_is_minint); - __ Goto(&minint_check_done); - - __ Bind(&if_is_minint); - // Check if {rhs} is -1. - Node* minusone = __ Int32Constant(-1); - Node* is_minus_one = __ Word32Equal(rhs, minusone); - __ DeoptimizeIf(DeoptimizeReason::kOverflow, VectorSlotPair(), is_minus_one, - frame_state); - __ Goto(&minint_check_done); + __ Bind(&if_lhs_notminint); + { + // Perform the actual integer division. + __ Goto(&done, __ Int32Div(lhs, rhs)); + } + } - __ Bind(&minint_check_done); - // Perform the actual integer division. - __ Goto(&done, __ Int32Div(lhs, rhs)); - } + __ Bind(&done); + Node* value = done.PhiAt(0); - __ Bind(&done); - Node* value = done.PhiAt(0); + // Check if the remainder is non-zero. + Node* check = __ Word32Equal(lhs, __ Int32Mul(value, rhs)); + __ DeoptimizeIfNot(DeoptimizeReason::kLostPrecision, VectorSlotPair(), + check, frame_state); - // Check if the remainder is non-zero. - Node* check = __ Word32Equal(lhs, __ Int32Mul(rhs, value)); - __ DeoptimizeIfNot(DeoptimizeReason::kLostPrecision, VectorSlotPair(), check, - frame_state); - - return value; + return value; + } } Node* EffectControlLinearizer::BuildUint32Mod(Node* lhs, Node* rhs) { @@ -1722,8 +1875,11 @@ Node* EffectControlLinearizer::LowerCheckedInt32Mod(Node* node, __ Bind(&if_lhs_negative); { - // The {lhs} is a negative integer. - Node* res = BuildUint32Mod(__ Int32Sub(zero, lhs), rhs); + // The {lhs} is a negative integer. This is very unlikely and + // we intentionally don't use the BuildUint32Mod() here, which + // would try to figure out whether {rhs} is a power of two, + // since this is intended to be a slow-path. + Node* res = __ Uint32Mod(__ Int32Sub(zero, lhs), rhs); // Check if we would have to return -0. __ DeoptimizeIf(DeoptimizeReason::kMinusZero, VectorSlotPair(), @@ -1739,22 +1895,38 @@ Node* EffectControlLinearizer::LowerCheckedUint32Div(Node* node, Node* frame_state) { Node* lhs = node->InputAt(0); Node* rhs = node->InputAt(1); - Node* zero = __ Int32Constant(0); - // Ensure that {rhs} is not zero, otherwise we'd have to return NaN. - Node* check = __ Word32Equal(rhs, zero); - __ DeoptimizeIf(DeoptimizeReason::kDivisionByZero, VectorSlotPair(), check, - frame_state); + // Check if the {rhs} is a known power of two. + Uint32Matcher m(rhs); + if (m.IsPowerOf2()) { + // Since we know that {rhs} is a power of two, we can perform a fast + // check to see if the relevant least significant bits of the {lhs} + // are all zero, and if so we know that we can perform a division + // safely (and fast by doing a logical - aka zero extending - right + // shift on {lhs}). + uint32_t divisor = m.Value(); + Node* mask = __ Uint32Constant(divisor - 1); + Node* shift = __ Uint32Constant(WhichPowerOf2(divisor)); + Node* check = __ Word32Equal(__ Word32And(lhs, mask), zero); + __ DeoptimizeIfNot(DeoptimizeReason::kLostPrecision, VectorSlotPair(), + check, frame_state); + return __ Word32Shr(lhs, shift); + } else { + // Ensure that {rhs} is not zero, otherwise we'd have to return NaN. + Node* check = __ Word32Equal(rhs, zero); + __ DeoptimizeIf(DeoptimizeReason::kDivisionByZero, VectorSlotPair(), check, + frame_state); - // Perform the actual unsigned integer division. - Node* value = __ Uint32Div(lhs, rhs); + // Perform the actual unsigned integer division. + Node* value = __ Uint32Div(lhs, rhs); - // Check if the remainder is non-zero. - check = __ Word32Equal(lhs, __ Int32Mul(rhs, value)); - __ DeoptimizeIfNot(DeoptimizeReason::kLostPrecision, VectorSlotPair(), check, - frame_state); - return value; + // Check if the remainder is non-zero. + check = __ Word32Equal(lhs, __ Int32Mul(rhs, value)); + __ DeoptimizeIfNot(DeoptimizeReason::kLostPrecision, VectorSlotPair(), + check, frame_state); + return value; + } } Node* EffectControlLinearizer::LowerCheckedUint32Mod(Node* node, @@ -1815,13 +1987,48 @@ Node* EffectControlLinearizer::LowerCheckedInt32ToTaggedSigned( Node* add = __ Int32AddWithOverflow(value, value); Node* check = __ Projection(1, add); - __ DeoptimizeIf(DeoptimizeReason::kOverflow, params.feedback(), check, + __ DeoptimizeIf(DeoptimizeReason::kLostPrecision, params.feedback(), check, frame_state); Node* result = __ Projection(0, add); result = ChangeInt32ToIntPtr(result); return result; } +Node* EffectControlLinearizer::LowerCheckedInt64ToInt32(Node* node, + Node* frame_state) { + Node* value = node->InputAt(0); + const CheckParameters& params = CheckParametersOf(node->op()); + + Node* value32 = __ TruncateInt64ToInt32(value); + Node* check = __ Word64Equal(__ ChangeInt32ToInt64(value32), value); + __ DeoptimizeIfNot(DeoptimizeReason::kLostPrecision, params.feedback(), check, + frame_state); + return value32; +} + +Node* EffectControlLinearizer::LowerCheckedInt64ToTaggedSigned( + Node* node, Node* frame_state) { + Node* value = node->InputAt(0); + const CheckParameters& params = CheckParametersOf(node->op()); + + Node* value32 = __ TruncateInt64ToInt32(value); + Node* check = __ Word64Equal(__ ChangeInt32ToInt64(value32), value); + __ DeoptimizeIfNot(DeoptimizeReason::kLostPrecision, params.feedback(), check, + frame_state); + + if (SmiValuesAre32Bits()) { + return ChangeInt64ToSmi(value); + } else { + Node* add = __ Int32AddWithOverflow(value32, value32); + Node* check = __ Projection(1, add); + __ DeoptimizeIf(DeoptimizeReason::kLostPrecision, params.feedback(), check, + frame_state); + Node* result = __ Projection(0, add); + result = ChangeInt32ToIntPtr(result); + return result; + } +} + Node* EffectControlLinearizer::LowerCheckedUint32ToInt32(Node* node, Node* frame_state) { Node* value = node->InputAt(0); @@ -1842,6 +2049,29 @@ Node* EffectControlLinearizer::LowerCheckedUint32ToTaggedSigned( return ChangeUint32ToSmi(value); } +Node* EffectControlLinearizer::LowerCheckedUint64ToInt32(Node* node, + Node* frame_state) { + Node* value = node->InputAt(0); + const CheckParameters& params = CheckParametersOf(node->op()); + + Node* check = __ Uint64LessThanOrEqual(value, __ Int64Constant(kMaxInt)); + __ DeoptimizeIfNot(DeoptimizeReason::kLostPrecision, params.feedback(), check, + frame_state); + return __ TruncateInt64ToInt32(value); +} + +Node* EffectControlLinearizer::LowerCheckedUint64ToTaggedSigned( + Node* node, Node* frame_state) { + Node* value = node->InputAt(0); + const CheckParameters& params = CheckParametersOf(node->op()); + + Node* check = + __ Uint64LessThanOrEqual(value, __ Int64Constant(Smi::kMaxValue)); + __ DeoptimizeIfNot(DeoptimizeReason::kLostPrecision, params.feedback(), check, + frame_state); + return ChangeInt64ToSmi(value); +} + Node* EffectControlLinearizer::BuildCheckedFloat64ToInt32( CheckForMinusZeroMode mode, const VectorSlotPair& feedback, Node* value, Node* frame_state) { @@ -2065,7 +2295,8 @@ Node* EffectControlLinearizer::LowerNumberToString(Node* node) { Operator::Properties properties = Operator::kEliminatable; CallDescriptor::Flags flags = CallDescriptor::kNoFlags; auto call_descriptor = Linkage::GetStubCallDescriptor( - graph()->zone(), callable.descriptor(), 0, flags, properties); + graph()->zone(), callable.descriptor(), + callable.descriptor().GetStackParameterCount(), flags, properties); return __ Call(call_descriptor, __ HeapConstant(callable.code()), argument, __ NoContextConstant()); } @@ -2521,7 +2752,8 @@ Node* EffectControlLinearizer::LowerTypeOf(Node* node) { Operator::Properties const properties = Operator::kEliminatable; CallDescriptor::Flags const flags = CallDescriptor::kNoAllocate; auto call_descriptor = Linkage::GetStubCallDescriptor( - graph()->zone(), callable.descriptor(), 0, flags, properties); + graph()->zone(), callable.descriptor(), + callable.descriptor().GetStackParameterCount(), flags, properties); return __ Call(call_descriptor, __ HeapConstant(callable.code()), obj, __ NoContextConstant()); } @@ -2533,7 +2765,8 @@ Node* EffectControlLinearizer::LowerToBoolean(Node* node) { Operator::Properties const properties = Operator::kEliminatable; CallDescriptor::Flags const flags = CallDescriptor::kNoAllocate; auto call_descriptor = Linkage::GetStubCallDescriptor( - graph()->zone(), callable.descriptor(), 0, flags, properties); + graph()->zone(), callable.descriptor(), + callable.descriptor().GetStackParameterCount(), flags, properties); return __ Call(call_descriptor, __ HeapConstant(callable.code()), obj, __ NoContextConstant()); } @@ -2721,7 +2954,8 @@ Node* EffectControlLinearizer::LowerNewArgumentsElements(Node* node) { Operator::Properties const properties = node->op()->properties(); CallDescriptor::Flags const flags = CallDescriptor::kNoFlags; auto call_descriptor = Linkage::GetStubCallDescriptor( - graph()->zone(), callable.descriptor(), 0, flags, properties); + graph()->zone(), callable.descriptor(), + callable.descriptor().GetStackParameterCount(), flags, properties); return __ Call(call_descriptor, __ HeapConstant(callable.code()), frame, length, __ SmiConstant(mapped_count), __ NoContextConstant()); } @@ -2765,26 +2999,13 @@ Node* EffectControlLinearizer::LowerNewConsString(Node* node) { Node* result = __ Allocate(NOT_TENURED, __ Int32Constant(ConsString::kSize)); __ StoreField(AccessBuilder::ForMap(), result, result_map); __ StoreField(AccessBuilder::ForNameHashField(), result, - jsgraph()->Int32Constant(Name::kEmptyHashField)); + __ Int32Constant(Name::kEmptyHashField)); __ StoreField(AccessBuilder::ForStringLength(), result, length); __ StoreField(AccessBuilder::ForConsStringFirst(), result, first); __ StoreField(AccessBuilder::ForConsStringSecond(), result, second); return result; } -Node* EffectControlLinearizer::LowerArrayBufferWasNeutered(Node* node) { - Node* value = node->InputAt(0); - - Node* value_bit_field = - __ LoadField(AccessBuilder::ForJSArrayBufferBitField(), value); - return __ Word32Equal( - __ Word32Equal( - __ Word32And(value_bit_field, - __ Int32Constant(JSArrayBuffer::WasNeutered::kMask)), - __ Int32Constant(0)), - __ Int32Constant(0)); -} - Node* EffectControlLinearizer::LowerSameValue(Node* node) { Node* lhs = node->InputAt(0); Node* rhs = node->InputAt(1); @@ -2794,7 +3015,8 @@ Node* EffectControlLinearizer::LowerSameValue(Node* node) { Operator::Properties properties = Operator::kEliminatable; CallDescriptor::Flags flags = CallDescriptor::kNoFlags; auto call_descriptor = Linkage::GetStubCallDescriptor( - graph()->zone(), callable.descriptor(), 0, flags, properties); + graph()->zone(), callable.descriptor(), + callable.descriptor().GetStackParameterCount(), flags, properties); return __ Call(call_descriptor, __ HeapConstant(callable.code()), lhs, rhs, __ NoContextConstant()); } @@ -2816,7 +3038,8 @@ Node* EffectControlLinearizer::LowerStringToNumber(Node* node) { Operator::Properties properties = Operator::kEliminatable; CallDescriptor::Flags flags = CallDescriptor::kNoFlags; auto call_descriptor = Linkage::GetStubCallDescriptor( - graph()->zone(), callable.descriptor(), 0, flags, properties); + graph()->zone(), callable.descriptor(), + callable.descriptor().GetStackParameterCount(), flags, properties); return __ Call(call_descriptor, __ HeapConstant(callable.code()), string, __ NoContextConstant()); } @@ -2828,9 +3051,9 @@ Node* EffectControlLinearizer::LowerStringCharCodeAt(Node* node) { // We need a loop here to properly deal with indirect strings // (SlicedString, ConsString and ThinString). auto loop = __ MakeLoopLabel(MachineRepresentation::kTagged, - MachineRepresentation::kWord32); + MachineType::PointerRepresentation()); auto loop_next = __ MakeLabel(MachineRepresentation::kTagged, - MachineRepresentation::kWord32); + MachineType::PointerRepresentation()); auto loop_done = __ MakeLabel(MachineRepresentation::kWord32); __ Goto(&loop, receiver, position); __ Bind(&loop); @@ -2897,11 +3120,11 @@ Node* EffectControlLinearizer::LowerStringCharCodeAt(Node* node) { __ Bind(&if_externalstring); { - // We need to bailout to the runtime for short external strings. + // We need to bailout to the runtime for uncached external strings. __ GotoIf(__ Word32Equal( __ Word32And(receiver_instance_type, - __ Int32Constant(kShortExternalStringMask)), - __ Int32Constant(kShortExternalStringTag)), + __ Int32Constant(kUncachedExternalStringMask)), + __ Int32Constant(kUncachedExternalStringTag)), &if_runtime); Node* receiver_data = __ LoadField( @@ -2917,16 +3140,14 @@ Node* EffectControlLinearizer::LowerStringCharCodeAt(Node* node) { __ Bind(&if_onebyte); { - Node* result = __ Load(MachineType::Uint8(), receiver_data, - ChangeInt32ToIntPtr(position)); + Node* result = __ Load(MachineType::Uint8(), receiver_data, position); __ Goto(&loop_done, result); } __ Bind(&if_twobyte); { - Node* result = __ Load( - MachineType::Uint16(), receiver_data, - __ Word32Shl(ChangeInt32ToIntPtr(position), __ Int32Constant(1))); + Node* result = __ Load(MachineType::Uint16(), receiver_data, + __ WordShl(position, __ IntPtrConstant(1))); __ Goto(&loop_done, result); } } @@ -2938,7 +3159,7 @@ Node* EffectControlLinearizer::LowerStringCharCodeAt(Node* node) { Node* receiver_parent = __ LoadField(AccessBuilder::ForSlicedStringParent(), receiver); __ Goto(&loop_next, receiver_parent, - __ Int32Add(position, ChangeSmiToInt32(receiver_offset))); + __ IntAdd(position, ChangeSmiToIntPtr(receiver_offset))); } __ Bind(&if_runtime); @@ -2948,7 +3169,7 @@ Node* EffectControlLinearizer::LowerStringCharCodeAt(Node* node) { auto call_descriptor = Linkage::GetRuntimeCallDescriptor( graph()->zone(), id, 2, properties, CallDescriptor::kNoFlags); Node* result = __ Call(call_descriptor, __ CEntryStubConstant(1), - receiver, ChangeInt32ToSmi(position), + receiver, ChangeIntPtrToSmi(position), __ ExternalConstant(ExternalReference::Create(id)), __ Int32Constant(2), __ NoContextConstant()); __ Goto(&loop_done, ChangeSmiToInt32(result)); @@ -2974,7 +3195,8 @@ Node* EffectControlLinearizer::LowerStringCodePointAt( Operator::Properties properties = Operator::kNoThrow | Operator::kNoWrite; CallDescriptor::Flags flags = CallDescriptor::kNoFlags; auto call_descriptor = Linkage::GetStubCallDescriptor( - graph()->zone(), callable.descriptor(), 0, flags, properties); + graph()->zone(), callable.descriptor(), + callable.descriptor().GetStackParameterCount(), flags, properties); return __ Call(call_descriptor, __ HeapConstant(callable.code()), receiver, position, __ NoContextConstant()); } @@ -3035,9 +3257,9 @@ Node* EffectControlLinearizer::LowerStringFromSingleCharCode(Node* node) { __ StoreField(AccessBuilder::ForMap(), vtrue2, __ HeapConstant(factory()->one_byte_string_map())); __ StoreField(AccessBuilder::ForNameHashField(), vtrue2, - __ IntPtrConstant(Name::kEmptyHashField)); + __ Int32Constant(Name::kEmptyHashField)); __ StoreField(AccessBuilder::ForStringLength(), vtrue2, - __ SmiConstant(1)); + __ Int32Constant(1)); __ Store( StoreRepresentation(MachineRepresentation::kWord8, kNoWriteBarrier), vtrue2, @@ -3059,8 +3281,9 @@ Node* EffectControlLinearizer::LowerStringFromSingleCharCode(Node* node) { __ StoreField(AccessBuilder::ForMap(), vfalse1, __ HeapConstant(factory()->string_map())); __ StoreField(AccessBuilder::ForNameHashField(), vfalse1, - __ IntPtrConstant(Name::kEmptyHashField)); - __ StoreField(AccessBuilder::ForStringLength(), vfalse1, __ SmiConstant(1)); + __ Int32Constant(Name::kEmptyHashField)); + __ StoreField(AccessBuilder::ForStringLength(), vfalse1, + __ Int32Constant(1)); __ Store( StoreRepresentation(MachineRepresentation::kWord16, kNoWriteBarrier), vfalse1, @@ -3083,7 +3306,8 @@ Node* EffectControlLinearizer::LowerStringToLowerCaseIntl(Node* node) { Operator::Properties properties = Operator::kNoDeopt | Operator::kNoThrow; CallDescriptor::Flags flags = CallDescriptor::kNoFlags; auto call_descriptor = Linkage::GetStubCallDescriptor( - graph()->zone(), callable.descriptor(), 0, flags, properties); + graph()->zone(), callable.descriptor(), + callable.descriptor().GetStackParameterCount(), flags, properties); return __ Call(call_descriptor, __ HeapConstant(callable.code()), receiver, __ NoContextConstant()); } @@ -3157,9 +3381,9 @@ Node* EffectControlLinearizer::LowerStringFromSingleCodePoint(Node* node) { __ StoreField(AccessBuilder::ForMap(), vtrue2, __ HeapConstant(factory()->one_byte_string_map())); __ StoreField(AccessBuilder::ForNameHashField(), vtrue2, - __ IntPtrConstant(Name::kEmptyHashField)); + __ Int32Constant(Name::kEmptyHashField)); __ StoreField(AccessBuilder::ForStringLength(), vtrue2, - __ SmiConstant(1)); + __ Int32Constant(1)); __ Store( StoreRepresentation(MachineRepresentation::kWord8, kNoWriteBarrier), vtrue2, @@ -3183,7 +3407,7 @@ Node* EffectControlLinearizer::LowerStringFromSingleCodePoint(Node* node) { __ StoreField(AccessBuilder::ForNameHashField(), vfalse1, __ IntPtrConstant(Name::kEmptyHashField)); __ StoreField(AccessBuilder::ForStringLength(), vfalse1, - __ SmiConstant(1)); + __ Int32Constant(1)); __ Store( StoreRepresentation(MachineRepresentation::kWord16, kNoWriteBarrier), vfalse1, @@ -3228,8 +3452,9 @@ Node* EffectControlLinearizer::LowerStringFromSingleCodePoint(Node* node) { __ StoreField(AccessBuilder::ForMap(), vfalse0, __ HeapConstant(factory()->string_map())); __ StoreField(AccessBuilder::ForNameHashField(), vfalse0, - __ IntPtrConstant(Name::kEmptyHashField)); - __ StoreField(AccessBuilder::ForStringLength(), vfalse0, __ SmiConstant(2)); + __ Int32Constant(Name::kEmptyHashField)); + __ StoreField(AccessBuilder::ForStringLength(), vfalse0, + __ Int32Constant(2)); __ Store( StoreRepresentation(MachineRepresentation::kWord32, kNoWriteBarrier), vfalse0, @@ -3252,7 +3477,8 @@ Node* EffectControlLinearizer::LowerStringIndexOf(Node* node) { Operator::Properties properties = Operator::kEliminatable; CallDescriptor::Flags flags = CallDescriptor::kNoFlags; auto call_descriptor = Linkage::GetStubCallDescriptor( - graph()->zone(), callable.descriptor(), 0, flags, properties); + graph()->zone(), callable.descriptor(), + callable.descriptor().GetStackParameterCount(), flags, properties); return __ Call(call_descriptor, __ HeapConstant(callable.code()), subject, search_string, position, __ NoContextConstant()); } @@ -3271,7 +3497,8 @@ Node* EffectControlLinearizer::LowerStringComparison(Callable const& callable, Operator::Properties properties = Operator::kEliminatable; CallDescriptor::Flags flags = CallDescriptor::kNoFlags; auto call_descriptor = Linkage::GetStubCallDescriptor( - graph()->zone(), callable.descriptor(), 0, flags, properties); + graph()->zone(), callable.descriptor(), + callable.descriptor().GetStackParameterCount(), flags, properties); return __ Call(call_descriptor, __ HeapConstant(callable.code()), lhs, rhs, __ NoContextConstant()); } @@ -3286,7 +3513,8 @@ Node* EffectControlLinearizer::LowerStringSubstring(Node* node) { Operator::Properties properties = Operator::kEliminatable; CallDescriptor::Flags flags = CallDescriptor::kNoFlags; auto call_descriptor = Linkage::GetStubCallDescriptor( - graph()->zone(), callable.descriptor(), 0, flags, properties); + graph()->zone(), callable.descriptor(), + callable.descriptor().GetStackParameterCount(), flags, properties); return __ Call(call_descriptor, __ HeapConstant(callable.code()), receiver, start, end, __ NoContextConstant()); } @@ -3314,10 +3542,25 @@ Node* EffectControlLinearizer::LowerCheckFloat64Hole(Node* node, CheckFloat64HoleParameters const& params = CheckFloat64HoleParametersOf(node->op()); Node* value = node->InputAt(0); - Node* check = __ Word32Equal(__ Float64ExtractHighWord32(value), - __ Int32Constant(kHoleNanUpper32)); - __ DeoptimizeIf(DeoptimizeReason::kHole, params.feedback(), check, - frame_state); + + auto if_nan = __ MakeDeferredLabel(); + auto done = __ MakeLabel(); + + // First check whether {value} is a NaN at all... + __ Branch(__ Float64Equal(value, value), &done, &if_nan); + + __ Bind(&if_nan); + { + // ...and only if {value} is a NaN, perform the expensive bit + // check. See http://crbug.com/v8/8264 for details. + Node* check = __ Word32Equal(__ Float64ExtractHighWord32(value), + __ Int32Constant(kHoleNanUpper32)); + __ DeoptimizeIf(DeoptimizeReason::kHole, params.feedback(), check, + frame_state); + __ Goto(&done); + } + + __ Bind(&done); return value; } @@ -3440,8 +3683,8 @@ Node* EffectControlLinearizer::AllocateHeapNumberWithValue(Node* value) { return result; } -Node* EffectControlLinearizer::ChangeInt32ToSmi(Node* value) { - return __ WordShl(ChangeInt32ToIntPtr(value), SmiShiftBitsConstant()); +Node* EffectControlLinearizer::ChangeIntPtrToSmi(Node* value) { + return __ WordShl(value, SmiShiftBitsConstant()); } Node* EffectControlLinearizer::ChangeInt32ToIntPtr(Node* value) { @@ -3458,6 +3701,15 @@ Node* EffectControlLinearizer::ChangeIntPtrToInt32(Node* value) { return value; } +Node* EffectControlLinearizer::ChangeInt32ToSmi(Node* value) { + return ChangeIntPtrToSmi(ChangeInt32ToIntPtr(value)); +} + +Node* EffectControlLinearizer::ChangeInt64ToSmi(Node* value) { + DCHECK(machine()->Is64()); + return ChangeIntPtrToSmi(value); +} + Node* EffectControlLinearizer::ChangeUint32ToUintPtr(Node* value) { if (machine()->Is64()) { value = __ ChangeUint32ToUint64(value); @@ -3482,6 +3734,11 @@ Node* EffectControlLinearizer::ChangeSmiToInt32(Node* value) { return value; } +Node* EffectControlLinearizer::ChangeSmiToInt64(Node* value) { + CHECK(machine()->Is64()); + return ChangeSmiToIntPtr(value); +} + Node* EffectControlLinearizer::ObjectIsSmi(Node* value) { return __ WordEqual(__ WordAnd(value, __ IntPtrConstant(kSmiTagMask)), __ IntPtrConstant(kSmiTag)); @@ -3578,7 +3835,8 @@ Node* EffectControlLinearizer::LowerEnsureWritableFastElements(Node* node) { Builtins::CallableFor(isolate(), Builtins::kCopyFastSmiOrObjectElements); CallDescriptor::Flags flags = CallDescriptor::kNoFlags; auto call_descriptor = Linkage::GetStubCallDescriptor( - graph()->zone(), callable.descriptor(), 0, flags, properties); + graph()->zone(), callable.descriptor(), + callable.descriptor().GetStackParameterCount(), flags, properties); Node* result = __ Call(call_descriptor, __ HeapConstant(callable.code()), object, __ NoContextConstant()); __ Goto(&done, result); @@ -3614,7 +3872,8 @@ Node* EffectControlLinearizer::LowerMaybeGrowFastElements(Node* node, Builtins::kGrowFastSmiOrObjectElements); CallDescriptor::Flags call_flags = CallDescriptor::kNoFlags; auto call_descriptor = Linkage::GetStubCallDescriptor( - graph()->zone(), callable.descriptor(), 0, call_flags, properties); + graph()->zone(), callable.descriptor(), + callable.descriptor().GetStackParameterCount(), call_flags, properties); Node* new_elements = __ Call(call_descriptor, __ HeapConstant(callable.code()), object, ChangeInt32ToSmi(index), __ NoContextConstant()); @@ -3830,12 +4089,6 @@ Node* EffectControlLinearizer::LowerLoadDataViewElement(Node* node) { Node* index = node->InputAt(2); Node* is_little_endian = node->InputAt(3); - // On 64-bit platforms, we need to feed a Word64 index to the Load and - // Store operators. - if (machine()->Is64()) { - index = __ ChangeUint32ToUint64(index); - } - // We need to keep the {buffer} alive so that the GC will not release the // ArrayBuffer (if there's any) as long as we are still operating on it. __ Retain(buffer); @@ -3878,12 +4131,6 @@ void EffectControlLinearizer::LowerStoreDataViewElement(Node* node) { Node* value = node->InputAt(3); Node* is_little_endian = node->InputAt(4); - // On 64-bit platforms, we need to feed a Word64 index to the Load and - // Store operators. - if (machine()->Is64()) { - index = __ ChangeUint32ToUint64(index); - } - // We need to keep the {buffer} alive so that the GC will not release the // ArrayBuffer (if there's any) as long as we are still operating on it. __ Retain(buffer); @@ -4366,7 +4613,8 @@ Node* EffectControlLinearizer::LowerConvertReceiver(Node* node) { Callable callable = Builtins::CallableFor(isolate(), Builtins::kToObject); CallDescriptor::Flags flags = CallDescriptor::kNoFlags; auto call_descriptor = Linkage::GetStubCallDescriptor( - graph()->zone(), callable.descriptor(), 0, flags, properties); + graph()->zone(), callable.descriptor(), + callable.descriptor().GetStackParameterCount(), flags, properties); Node* native_context = __ LoadField( AccessBuilder::ForJSGlobalProxyNativeContext(), global_proxy); Node* result = __ Call(call_descriptor, __ HeapConstant(callable.code()), @@ -4401,7 +4649,8 @@ Node* EffectControlLinearizer::LowerConvertReceiver(Node* node) { Callable callable = Builtins::CallableFor(isolate(), Builtins::kToObject); CallDescriptor::Flags flags = CallDescriptor::kNoFlags; auto call_descriptor = Linkage::GetStubCallDescriptor( - graph()->zone(), callable.descriptor(), 0, flags, properties); + graph()->zone(), callable.descriptor(), + callable.descriptor().GetStackParameterCount(), flags, properties); Node* native_context = __ LoadField( AccessBuilder::ForJSGlobalProxyNativeContext(), global_proxy); Node* result = __ Call(call_descriptor, __ HeapConstant(callable.code()), @@ -4762,7 +5011,8 @@ Node* EffectControlLinearizer::LowerFindOrderedHashMapEntry(Node* node) { Operator::Properties const properties = node->op()->properties(); CallDescriptor::Flags const flags = CallDescriptor::kNoFlags; auto call_descriptor = Linkage::GetStubCallDescriptor( - graph()->zone(), callable.descriptor(), 0, flags, properties); + graph()->zone(), callable.descriptor(), + callable.descriptor().GetStackParameterCount(), flags, properties); return __ Call(call_descriptor, __ HeapConstant(callable.code()), table, key, __ NoContextConstant()); } @@ -4799,14 +5049,14 @@ Node* EffectControlLinearizer::LowerFindOrderedHashMapEntryForInt32Key( kHeapObjectTag)))); auto loop = __ MakeLoopLabel(MachineType::PointerRepresentation()); - auto done = __ MakeLabel(MachineRepresentation::kWord32); + auto done = __ MakeLabel(MachineType::PointerRepresentation()); __ Goto(&loop, first_entry); __ Bind(&loop); { Node* entry = loop.PhiAt(0); Node* check = __ WordEqual(entry, __ IntPtrConstant(OrderedHashMap::kNotFound)); - __ GotoIf(check, &done, __ Int32Constant(-1)); + __ GotoIf(check, &done, entry); entry = __ IntAdd( __ IntMul(entry, __ IntPtrConstant(OrderedHashMap::kEntrySize)), number_of_buckets); @@ -4835,10 +5085,7 @@ Node* EffectControlLinearizer::LowerFindOrderedHashMapEntryForInt32Key( &if_match, &if_notmatch); __ Bind(&if_match); - { - Node* index = ChangeIntPtrToInt32(entry); - __ Goto(&done, index); - } + __ Goto(&done, entry); __ Bind(&if_notmatch); { |