diff options
Diffstat (limited to 'deps/v8/src/compiler/effect-control-linearizer.cc')
-rw-r--r-- | deps/v8/src/compiler/effect-control-linearizer.cc | 391 |
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) { |