summaryrefslogtreecommitdiff
path: root/deps/v8/src/compiler/effect-control-linearizer.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/compiler/effect-control-linearizer.cc')
-rw-r--r--deps/v8/src/compiler/effect-control-linearizer.cc391
1 files changed, 216 insertions, 175 deletions
diff --git a/deps/v8/src/compiler/effect-control-linearizer.cc b/deps/v8/src/compiler/effect-control-linearizer.cc
index 290a3b5f34..52cbefb15c 100644
--- a/deps/v8/src/compiler/effect-control-linearizer.cc
+++ b/deps/v8/src/compiler/effect-control-linearizer.cc
@@ -13,7 +13,7 @@
#include "src/compiler/node-properties.h"
#include "src/compiler/node.h"
#include "src/compiler/schedule.h"
-#include "src/factory-inl.h"
+#include "src/heap/factory-inl.h"
namespace v8 {
namespace internal {
@@ -682,9 +682,6 @@ 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;
@@ -827,11 +824,11 @@ bool EffectControlLinearizer::TryWireInStateEffect(Node* node,
case IrOpcode::kDeadValue:
result = LowerDeadValue(node);
break;
- case IrOpcode::kStringFromCharCode:
- result = LowerStringFromCharCode(node);
+ case IrOpcode::kStringFromSingleCharCode:
+ result = LowerStringFromSingleCharCode(node);
break;
- case IrOpcode::kStringFromCodePoint:
- result = LowerStringFromCodePoint(node);
+ case IrOpcode::kStringFromSingleCodePoint:
+ result = LowerStringFromSingleCodePoint(node);
break;
case IrOpcode::kStringIndexOf:
result = LowerStringIndexOf(node);
@@ -842,21 +839,12 @@ bool EffectControlLinearizer::TryWireInStateEffect(Node* node,
case IrOpcode::kStringToNumber:
result = LowerStringToNumber(node);
break;
- case IrOpcode::kStringCharAt:
- result = LowerStringCharAt(node);
- break;
case IrOpcode::kStringCharCodeAt:
result = LowerStringCharCodeAt(node);
break;
- case IrOpcode::kSeqStringCharCodeAt:
- result = LowerSeqStringCharCodeAt(node);
- break;
case IrOpcode::kStringCodePointAt:
result = LowerStringCodePointAt(node, UnicodeEncodingOf(node->op()));
break;
- case IrOpcode::kSeqStringCodePointAt:
- result = LowerSeqStringCodePointAt(node, UnicodeEncodingOf(node->op()));
- break;
case IrOpcode::kStringToLowerCaseIntl:
result = LowerStringToLowerCaseIntl(node);
break;
@@ -878,6 +866,24 @@ bool EffectControlLinearizer::TryWireInStateEffect(Node* node,
case IrOpcode::kNumberIsFloat64Hole:
result = LowerNumberIsFloat64Hole(node);
break;
+ case IrOpcode::kNumberIsFinite:
+ result = LowerNumberIsFinite(node);
+ break;
+ case IrOpcode::kObjectIsFiniteNumber:
+ result = LowerObjectIsFiniteNumber(node);
+ break;
+ case IrOpcode::kNumberIsInteger:
+ result = LowerNumberIsInteger(node);
+ break;
+ case IrOpcode::kObjectIsInteger:
+ result = LowerObjectIsInteger(node);
+ break;
+ case IrOpcode::kNumberIsSafeInteger:
+ result = LowerNumberIsSafeInteger(node);
+ break;
+ case IrOpcode::kObjectIsSafeInteger:
+ result = LowerObjectIsSafeInteger(node);
+ break;
case IrOpcode::kCheckFloat64Hole:
result = LowerCheckFloat64Hole(node, frame_state);
break;
@@ -1500,24 +1506,6 @@ 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* check = __ Word32Equal(
- __ Word32And(
- value_instance_type,
- __ Int32Constant(kStringRepresentationMask | kIsNotStringMask)),
- __ Int32Constant(kSeqStringTag | kStringTag));
- __ DeoptimizeIfNot(DeoptimizeReason::kWrongInstanceType, VectorSlotPair(),
- check, frame_state);
- return value;
-}
-
Node* EffectControlLinearizer::LowerCheckInternalizedString(Node* node,
Node* frame_state) {
Node* value = node->InputAt(0);
@@ -2179,6 +2167,118 @@ Node* EffectControlLinearizer::LowerNumberIsFloat64Hole(Node* node) {
return check;
}
+Node* EffectControlLinearizer::LowerNumberIsFinite(Node* node) {
+ Node* number = node->InputAt(0);
+ Node* diff = __ Float64Sub(number, number);
+ Node* check = __ Float64Equal(diff, diff);
+ return check;
+}
+
+Node* EffectControlLinearizer::LowerObjectIsFiniteNumber(Node* node) {
+ Node* object = node->InputAt(0);
+ Node* zero = __ Int32Constant(0);
+ Node* one = __ Int32Constant(1);
+
+ auto done = __ MakeLabel(MachineRepresentation::kBit);
+
+ // Check if {object} is a Smi.
+ __ GotoIf(ObjectIsSmi(object), &done, one);
+
+ // Check if {object} is a HeapNumber.
+ Node* value_map = __ LoadField(AccessBuilder::ForMap(), object);
+ __ GotoIfNot(__ WordEqual(value_map, __ HeapNumberMapConstant()), &done,
+ zero);
+
+ // {object} is a HeapNumber.
+ Node* value = __ LoadField(AccessBuilder::ForHeapNumberValue(), object);
+ Node* diff = __ Float64Sub(value, value);
+ Node* check = __ Float64Equal(diff, diff);
+ __ Goto(&done, check);
+
+ __ Bind(&done);
+ return done.PhiAt(0);
+}
+
+Node* EffectControlLinearizer::LowerNumberIsInteger(Node* node) {
+ Node* number = node->InputAt(0);
+ Node* trunc = BuildFloat64RoundTruncate(number);
+ Node* diff = __ Float64Sub(number, trunc);
+ Node* check = __ Float64Equal(diff, __ Float64Constant(0));
+ return check;
+}
+
+Node* EffectControlLinearizer::LowerObjectIsInteger(Node* node) {
+ Node* object = node->InputAt(0);
+ Node* zero = __ Int32Constant(0);
+ Node* one = __ Int32Constant(1);
+
+ auto done = __ MakeLabel(MachineRepresentation::kBit);
+
+ // Check if {object} is a Smi.
+ __ GotoIf(ObjectIsSmi(object), &done, one);
+
+ // Check if {object} is a HeapNumber.
+ Node* value_map = __ LoadField(AccessBuilder::ForMap(), object);
+ __ GotoIfNot(__ WordEqual(value_map, __ HeapNumberMapConstant()), &done,
+ zero);
+
+ // {object} is a HeapNumber.
+ Node* value = __ LoadField(AccessBuilder::ForHeapNumberValue(), object);
+ Node* trunc = BuildFloat64RoundTruncate(value);
+ Node* diff = __ Float64Sub(value, trunc);
+ Node* check = __ Float64Equal(diff, __ Float64Constant(0));
+ __ Goto(&done, check);
+
+ __ Bind(&done);
+ return done.PhiAt(0);
+}
+
+Node* EffectControlLinearizer::LowerNumberIsSafeInteger(Node* node) {
+ Node* number = node->InputAt(0);
+ Node* zero = __ Int32Constant(0);
+ auto done = __ MakeLabel(MachineRepresentation::kBit);
+
+ Node* trunc = BuildFloat64RoundTruncate(number);
+ Node* diff = __ Float64Sub(number, trunc);
+ Node* check = __ Float64Equal(diff, __ Float64Constant(0));
+ __ GotoIfNot(check, &done, zero);
+ Node* in_range = __ Float64LessThanOrEqual(
+ __ Float64Abs(trunc), __ Float64Constant(kMaxSafeInteger));
+ __ Goto(&done, in_range);
+
+ __ Bind(&done);
+ return done.PhiAt(0);
+}
+
+Node* EffectControlLinearizer::LowerObjectIsSafeInteger(Node* node) {
+ Node* object = node->InputAt(0);
+ Node* zero = __ Int32Constant(0);
+ Node* one = __ Int32Constant(1);
+
+ auto done = __ MakeLabel(MachineRepresentation::kBit);
+
+ // Check if {object} is a Smi.
+ __ GotoIf(ObjectIsSmi(object), &done, one);
+
+ // Check if {object} is a HeapNumber.
+ Node* value_map = __ LoadField(AccessBuilder::ForMap(), object);
+ __ GotoIfNot(__ WordEqual(value_map, __ HeapNumberMapConstant()), &done,
+ zero);
+
+ // {object} is a HeapNumber.
+ Node* value = __ LoadField(AccessBuilder::ForHeapNumberValue(), object);
+ Node* trunc = BuildFloat64RoundTruncate(value);
+ Node* diff = __ Float64Sub(value, trunc);
+ Node* check = __ Float64Equal(diff, __ Float64Constant(0));
+ __ GotoIfNot(check, &done, zero);
+ Node* in_range = __ Float64LessThanOrEqual(
+ __ Float64Abs(trunc), __ Float64Constant(kMaxSafeInteger));
+ __ Goto(&done, in_range);
+
+ __ Bind(&done);
+ return done.PhiAt(0);
+}
+
Node* EffectControlLinearizer::LowerObjectIsMinusZero(Node* node) {
Node* value = node->InputAt(0);
Node* zero = __ Int32Constant(0);
@@ -2566,7 +2666,7 @@ Node* EffectControlLinearizer::LowerNewSmiOrObjectElements(Node* node) {
Node* EffectControlLinearizer::LowerNewArgumentsElements(Node* node) {
Node* frame = NodeProperties::GetValueInput(node, 0);
Node* length = NodeProperties::GetValueInput(node, 1);
- int mapped_count = OpParameter<int>(node);
+ int mapped_count = NewArgumentsElementsMappedCountOf(node->op());
Callable const callable =
Builtins::CallableFor(isolate(), Builtins::kNewArgumentsElements);
@@ -2673,20 +2773,6 @@ Node* EffectControlLinearizer::LowerStringToNumber(Node* node) {
__ NoContextConstant());
}
-Node* EffectControlLinearizer::LowerStringCharAt(Node* node) {
- Node* receiver = node->InputAt(0);
- Node* position = node->InputAt(1);
-
- Callable const callable =
- Builtins::CallableFor(isolate(), Builtins::kStringCharAt);
- Operator::Properties properties = Operator::kNoThrow | Operator::kNoWrite;
- CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
- auto call_descriptor = Linkage::GetStubCallDescriptor(
- isolate(), graph()->zone(), callable.descriptor(), 0, flags, properties);
- return __ Call(call_descriptor, __ HeapConstant(callable.code()), receiver,
- position, __ NoContextConstant());
-}
-
Node* EffectControlLinearizer::LowerStringCharCodeAt(Node* node) {
Node* receiver = node->InputAt(0);
Node* position = node->InputAt(1);
@@ -2865,132 +2951,78 @@ Node* EffectControlLinearizer::LoadFromSeqString(Node* receiver, Node* position,
return done.PhiAt(0);
}
-Node* EffectControlLinearizer::LowerSeqStringCharCodeAt(Node* node) {
- Node* receiver = node->InputAt(0);
- Node* position = node->InputAt(1);
-
- Node* map = __ LoadField(AccessBuilder::ForMap(), receiver);
- Node* instance_type = __ LoadField(AccessBuilder::ForMapInstanceType(), map);
- Node* is_one_byte = __ Word32Equal(
- __ Word32And(instance_type, __ Int32Constant(kStringEncodingMask)),
- __ Int32Constant(kOneByteStringTag));
-
- return LoadFromSeqString(receiver, position, is_one_byte);
-}
-
-Node* EffectControlLinearizer::LowerSeqStringCodePointAt(
- Node* node, UnicodeEncoding encoding) {
- Node* receiver = node->InputAt(0);
- Node* position = node->InputAt(1);
-
- Node* map = __ LoadField(AccessBuilder::ForMap(), receiver);
- Node* instance_type = __ LoadField(AccessBuilder::ForMapInstanceType(), map);
- Node* is_one_byte = __ Word32Equal(
- __ Word32And(instance_type, __ Int32Constant(kStringEncodingMask)),
- __ Int32Constant(kOneByteStringTag));
-
- Node* first_char_code = LoadFromSeqString(receiver, position, is_one_byte);
-
- auto return_result = __ MakeLabel(MachineRepresentation::kWord32);
-
- // Check if first character code is outside of interval [0xD800, 0xDBFF].
- Node* first_out =
- __ Word32Equal(__ Word32And(first_char_code, __ Int32Constant(0xFC00)),
- __ Int32Constant(0xD800));
- // Return first character code.
- __ GotoIfNot(first_out, &return_result, first_char_code);
- // Check if position + 1 is still in range.
- Node* length = ChangeSmiToInt32(
- __ LoadField(AccessBuilder::ForStringLength(), receiver));
- Node* next_position = __ Int32Add(position, __ Int32Constant(1));
- Node* next_position_in_range = __ Int32LessThan(next_position, length);
- __ GotoIfNot(next_position_in_range, &return_result, first_char_code);
-
- // Load second character code.
- Node* second_char_code =
- LoadFromSeqString(receiver, next_position, is_one_byte);
- // Check if second character code is outside of interval [0xDC00, 0xDFFF].
- Node* second_out =
- __ Word32Equal(__ Word32And(second_char_code, __ Int32Constant(0xFC00)),
- __ Int32Constant(0xDC00));
- __ GotoIfNot(second_out, &return_result, first_char_code);
-
- Node* result;
- switch (encoding) {
- case UnicodeEncoding::UTF16:
- result = __ Word32Or(
-// Need to swap the order for big-endian platforms
-#if V8_TARGET_BIG_ENDIAN
- __ Word32Shl(first_char_code, __ Int32Constant(16)),
- second_char_code);
-#else
- __ Word32Shl(second_char_code, __ Int32Constant(16)),
- first_char_code);
-#endif
- break;
- case UnicodeEncoding::UTF32: {
- // Convert UTF16 surrogate pair into |word32| code point, encoded as
- // UTF32.
- Node* surrogate_offset =
- __ Int32Constant(0x10000 - (0xD800 << 10) - 0xDC00);
-
- // (lead << 10) + trail + SURROGATE_OFFSET
- result = __ Int32Add(__ Word32Shl(first_char_code, __ Int32Constant(10)),
- __ Int32Add(second_char_code, surrogate_offset));
- break;
- }
- }
- __ Goto(&return_result, result);
-
- __ Bind(&return_result);
- return return_result.PhiAt(0);
-}
-
-Node* EffectControlLinearizer::LowerStringFromCharCode(Node* node) {
+Node* EffectControlLinearizer::LowerStringFromSingleCharCode(Node* node) {
Node* value = node->InputAt(0);
+ Node* code = __ Word32And(value, __ Uint32Constant(0xFFFF));
- auto runtime_call = __ MakeDeferredLabel();
- auto if_undefined = __ MakeDeferredLabel();
+ auto if_not_one_byte = __ MakeDeferredLabel();
+ auto cache_miss = __ MakeDeferredLabel();
auto done = __ MakeLabel(MachineRepresentation::kTagged);
- // Compute the character code.
- Node* code = __ Word32And(value, __ Int32Constant(String::kMaxUtf16CodeUnit));
+ // Check if the {code} is a one byte character
+ Node* check1 = __ Uint32LessThanOrEqual(
+ code, __ Uint32Constant(String::kMaxOneByteCharCode));
+ __ GotoIfNot(check1, &if_not_one_byte);
+ {
+ // Load the isolate wide single character string cache.
+ Node* cache = __ HeapConstant(factory()->single_character_string_cache());
+
+ // Compute the {cache} index for {code}.
+ Node* index = machine()->Is32() ? code : __ ChangeUint32ToUint64(code);
- // Check if the {code} is a one-byte char code.
- Node* check0 = __ Int32LessThanOrEqual(
- code, __ Int32Constant(String::kMaxOneByteCharCode));
- __ GotoIfNot(check0, &runtime_call);
+ // Check if we have an entry for the {code} in the single character string
+ // cache already.
+ Node* entry =
+ __ LoadElement(AccessBuilder::ForFixedArrayElement(), cache, index);
- // Load the isolate wide single character string cache.
- Node* cache = __ HeapConstant(factory()->single_character_string_cache());
+ Node* check2 = __ WordEqual(entry, __ UndefinedConstant());
+ __ GotoIf(check2, &cache_miss);
- // Compute the {cache} index for {code}.
- Node* index = machine()->Is32() ? code : __ ChangeUint32ToUint64(code);
+ // Use the {entry} from the {cache}.
+ __ Goto(&done, entry);
- // Check if we have an entry for the {code} in the single character string
- // cache already.
- Node* entry =
- __ LoadElement(AccessBuilder::ForFixedArrayElement(), cache, index);
+ __ Bind(&cache_miss);
+ {
+ // Allocate a new SeqOneByteString for {code}.
+ Node* vtrue2 = __ Allocate(
+ NOT_TENURED, __ Int32Constant(SeqOneByteString::SizeFor(1)));
+ __ StoreField(AccessBuilder::ForMap(), vtrue2,
+ __ HeapConstant(factory()->one_byte_string_map()));
+ __ StoreField(AccessBuilder::ForNameHashField(), vtrue2,
+ __ IntPtrConstant(Name::kEmptyHashField));
+ __ StoreField(AccessBuilder::ForStringLength(), vtrue2,
+ __ SmiConstant(1));
+ __ Store(
+ StoreRepresentation(MachineRepresentation::kWord8, kNoWriteBarrier),
+ vtrue2,
+ __ IntPtrConstant(SeqOneByteString::kHeaderSize - kHeapObjectTag),
+ code);
- Node* check1 = __ WordEqual(entry, __ UndefinedConstant());
- __ GotoIf(check1, &runtime_call);
- __ Goto(&done, entry);
+ // Remember it in the {cache}.
+ __ StoreElement(AccessBuilder::ForFixedArrayElement(), cache, index,
+ vtrue2);
+ __ Goto(&done, vtrue2);
+ }
+ }
- // Let %StringFromCharCode handle this case.
- // TODO(turbofan): At some point we may consider adding a stub for this
- // deferred case, so that we don't need to call to C++ here.
- __ Bind(&runtime_call);
+ __ Bind(&if_not_one_byte);
{
- Operator::Properties properties = Operator::kNoDeopt | Operator::kNoThrow;
- Runtime::FunctionId id = Runtime::kStringCharFromCode;
- auto call_descriptor = Linkage::GetRuntimeCallDescriptor(
- graph()->zone(), id, 1, properties, CallDescriptor::kNoFlags);
- Node* vtrue1 = __ Call(
- call_descriptor, __ CEntryStubConstant(1), ChangeInt32ToSmi(code),
- __ ExternalConstant(ExternalReference(id, isolate())),
- __ Int32Constant(1), __ NoContextConstant());
- __ Goto(&done, vtrue1);
+ // Allocate a new SeqTwoByteString for {code}.
+ Node* vfalse1 = __ Allocate(NOT_TENURED,
+ __ Int32Constant(SeqTwoByteString::SizeFor(1)));
+ __ StoreField(AccessBuilder::ForMap(), vfalse1,
+ __ HeapConstant(factory()->string_map()));
+ __ StoreField(AccessBuilder::ForNameHashField(), vfalse1,
+ __ IntPtrConstant(Name::kEmptyHashField));
+ __ StoreField(AccessBuilder::ForStringLength(), vfalse1, __ SmiConstant(1));
+ __ Store(
+ StoreRepresentation(MachineRepresentation::kWord16, kNoWriteBarrier),
+ vfalse1,
+ __ IntPtrConstant(SeqTwoByteString::kHeaderSize - kHeapObjectTag),
+ code);
+ __ Goto(&done, vfalse1);
}
+
__ Bind(&done);
return done.PhiAt(0);
}
@@ -3035,7 +3067,7 @@ Node* EffectControlLinearizer::LowerStringToUpperCaseIntl(Node* node) {
#endif // V8_INTL_SUPPORT
-Node* EffectControlLinearizer::LowerStringFromCodePoint(Node* node) {
+Node* EffectControlLinearizer::LowerStringFromSingleCodePoint(Node* node) {
Node* value = node->InputAt(0);
Node* code = value;
@@ -3135,7 +3167,11 @@ Node* EffectControlLinearizer::LowerStringFromCodePoint(Node* node) {
__ Int32Constant(0xDC00));
// codpoint = (trail << 16) | lead;
+#if V8_TARGET_BIG_ENDIAN
+ code = __ Word32Or(__ Word32Shl(lead, __ Int32Constant(16)), trail);
+#else
code = __ Word32Or(__ Word32Shl(trail, __ Int32Constant(16)), lead);
+#endif
break;
}
}
@@ -4278,9 +4314,8 @@ Maybe<Node*> EffectControlLinearizer::LowerFloat64RoundUp(Node* node) {
}
Node* EffectControlLinearizer::BuildFloat64RoundDown(Node* value) {
- Node* round_down = __ Float64RoundDown(value);
- if (round_down != nullptr) {
- return round_down;
+ if (machine()->Float64RoundDown().IsSupported()) {
+ return __ Float64RoundDown(value);
}
Node* const input = value;
@@ -4424,14 +4459,10 @@ Maybe<Node*> EffectControlLinearizer::LowerFloat64RoundTiesEven(Node* node) {
return Just(done.PhiAt(0));
}
-Maybe<Node*> EffectControlLinearizer::LowerFloat64RoundTruncate(Node* node) {
- // Nothing to be done if a fast hardware instruction is available.
+Node* EffectControlLinearizer::BuildFloat64RoundTruncate(Node* input) {
if (machine()->Float64RoundTruncate().IsSupported()) {
- return Nothing<Node*>();
+ return __ Float64RoundTruncate(input);
}
-
- Node* const input = node->InputAt(0);
-
// General case for trunc.
//
// if 0.0 < input then
@@ -4512,7 +4543,17 @@ Maybe<Node*> EffectControlLinearizer::LowerFloat64RoundTruncate(Node* node) {
__ Goto(&done, input);
}
__ Bind(&done);
- return Just(done.PhiAt(0));
+ return done.PhiAt(0);
+}
+
+Maybe<Node*> EffectControlLinearizer::LowerFloat64RoundTruncate(Node* node) {
+ // Nothing to be done if a fast hardware instruction is available.
+ if (machine()->Float64RoundTruncate().IsSupported()) {
+ return Nothing<Node*>();
+ }
+
+ Node* const input = node->InputAt(0);
+ return Just(BuildFloat64RoundTruncate(input));
}
Node* EffectControlLinearizer::LowerFindOrderedHashMapEntry(Node* node) {