| Index: src/code-stub-assembler.cc
|
| diff --git a/src/code-stub-assembler.cc b/src/code-stub-assembler.cc
|
| index 7ed1fbfda56e9725b27bca24ec5e820a524bee1a..1a4fed6796f06136efb84b6eac9b47f7442f3885 100644
|
| --- a/src/code-stub-assembler.cc
|
| +++ b/src/code-stub-assembler.cc
|
| @@ -1052,6 +1052,44 @@ Node* CodeStubAssembler::LoadFixedArrayElement(Node* object, Node* index_node,
|
| return Load(MachineType::AnyTagged(), object, offset);
|
| }
|
|
|
| +Node* CodeStubAssembler::LoadFixedTypedArrayElement(
|
| + Node* data_pointer, Node* index_node, ElementsKind elements_kind,
|
| + ParameterMode parameter_mode) {
|
| + Node* offset =
|
| + ElementOffsetFromIndex(index_node, elements_kind, parameter_mode, 0);
|
| + MachineType type;
|
| + switch (elements_kind) {
|
| + case UINT8_ELEMENTS: /* fall through */
|
| + case UINT8_CLAMPED_ELEMENTS:
|
| + type = MachineType::Uint8();
|
| + break;
|
| + case INT8_ELEMENTS:
|
| + type = MachineType::Int8();
|
| + break;
|
| + case UINT16_ELEMENTS:
|
| + type = MachineType::Uint16();
|
| + break;
|
| + case INT16_ELEMENTS:
|
| + type = MachineType::Int16();
|
| + break;
|
| + case UINT32_ELEMENTS:
|
| + type = MachineType::Uint32();
|
| + break;
|
| + case INT32_ELEMENTS:
|
| + type = MachineType::Int32();
|
| + break;
|
| + case FLOAT32_ELEMENTS:
|
| + type = MachineType::Float32();
|
| + break;
|
| + case FLOAT64_ELEMENTS:
|
| + type = MachineType::Float64();
|
| + break;
|
| + default:
|
| + UNREACHABLE();
|
| + }
|
| + return Load(type, data_pointer, offset);
|
| +}
|
| +
|
| Node* CodeStubAssembler::LoadAndUntagToWord32FixedArrayElement(
|
| Node* object, Node* index_node, int additional_offset,
|
| ParameterMode parameter_mode) {
|
| @@ -6146,6 +6184,120 @@ void CodeStubAssembler::BuildFastFixedArrayForEach(
|
| : IndexAdvanceMode::kPost);
|
| }
|
|
|
| +void CodeStubAssembler::BranchIfNumericRelationalComparison(
|
| + RelationalComparisonMode mode, compiler::Node* lhs, compiler::Node* rhs,
|
| + Label* if_true, Label* if_false) {
|
| + typedef compiler::Node Node;
|
| +
|
| + Label end(this);
|
| + Variable result(this, MachineRepresentation::kTagged);
|
| +
|
| + // Shared entry for floating point comparison.
|
| + Label do_fcmp(this);
|
| + Variable var_fcmp_lhs(this, MachineRepresentation::kFloat64),
|
| + var_fcmp_rhs(this, MachineRepresentation::kFloat64);
|
| +
|
| + // Check if the {lhs} is a Smi or a HeapObject.
|
| + Label if_lhsissmi(this), if_lhsisnotsmi(this);
|
| + Branch(TaggedIsSmi(lhs), &if_lhsissmi, &if_lhsisnotsmi);
|
| +
|
| + Bind(&if_lhsissmi);
|
| + {
|
| + // Check if {rhs} is a Smi or a HeapObject.
|
| + Label if_rhsissmi(this), if_rhsisnotsmi(this);
|
| + Branch(TaggedIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi);
|
| +
|
| + Bind(&if_rhsissmi);
|
| + {
|
| + // Both {lhs} and {rhs} are Smi, so just perform a fast Smi comparison.
|
| + switch (mode) {
|
| + case kLessThan:
|
| + BranchIfSmiLessThan(lhs, rhs, if_true, if_false);
|
| + break;
|
| + case kLessThanOrEqual:
|
| + BranchIfSmiLessThanOrEqual(lhs, rhs, if_true, if_false);
|
| + break;
|
| + case kGreaterThan:
|
| + BranchIfSmiLessThan(rhs, lhs, if_true, if_false);
|
| + break;
|
| + case kGreaterThanOrEqual:
|
| + BranchIfSmiLessThanOrEqual(rhs, lhs, if_true, if_false);
|
| + break;
|
| + }
|
| + }
|
| +
|
| + Bind(&if_rhsisnotsmi);
|
| + {
|
| + Assert(WordEqual(LoadMap(rhs), HeapNumberMapConstant()));
|
| + // Convert the {lhs} and {rhs} to floating point values, and
|
| + // perform a floating point comparison.
|
| + var_fcmp_lhs.Bind(SmiToFloat64(lhs));
|
| + var_fcmp_rhs.Bind(LoadHeapNumberValue(rhs));
|
| + Goto(&do_fcmp);
|
| + }
|
| + }
|
| +
|
| + Bind(&if_lhsisnotsmi);
|
| + {
|
| + Assert(WordEqual(LoadMap(lhs), HeapNumberMapConstant()));
|
| +
|
| + // Check if {rhs} is a Smi or a HeapObject.
|
| + Label if_rhsissmi(this), if_rhsisnotsmi(this);
|
| + Branch(TaggedIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi);
|
| +
|
| + Bind(&if_rhsissmi);
|
| + {
|
| + // Convert the {lhs} and {rhs} to floating point values, and
|
| + // perform a floating point comparison.
|
| + var_fcmp_lhs.Bind(LoadHeapNumberValue(lhs));
|
| + var_fcmp_rhs.Bind(SmiToFloat64(rhs));
|
| + Goto(&do_fcmp);
|
| + }
|
| +
|
| + Bind(&if_rhsisnotsmi);
|
| + {
|
| + Assert(WordEqual(LoadMap(rhs), HeapNumberMapConstant()));
|
| +
|
| + // Convert the {lhs} and {rhs} to floating point values, and
|
| + // perform a floating point comparison.
|
| + var_fcmp_lhs.Bind(LoadHeapNumberValue(lhs));
|
| + var_fcmp_rhs.Bind(LoadHeapNumberValue(rhs));
|
| + Goto(&do_fcmp);
|
| + }
|
| + }
|
| +
|
| + Bind(&do_fcmp);
|
| + {
|
| + // Load the {lhs} and {rhs} floating point values.
|
| + Node* lhs = var_fcmp_lhs.value();
|
| + Node* rhs = var_fcmp_rhs.value();
|
| +
|
| + // Perform a fast floating point comparison.
|
| + switch (mode) {
|
| + case kLessThan:
|
| + BranchIfFloat64LessThan(lhs, rhs, if_true, if_false);
|
| + break;
|
| + case kLessThanOrEqual:
|
| + BranchIfFloat64LessThanOrEqual(lhs, rhs, if_true, if_false);
|
| + break;
|
| + case kGreaterThan:
|
| + BranchIfFloat64GreaterThan(lhs, rhs, if_true, if_false);
|
| + break;
|
| + case kGreaterThanOrEqual:
|
| + BranchIfFloat64GreaterThanOrEqual(lhs, rhs, if_true, if_false);
|
| + break;
|
| + }
|
| + }
|
| +}
|
| +
|
| +void CodeStubAssembler::GotoUnlessNumberLessThan(compiler::Node* lhs,
|
| + compiler::Node* rhs,
|
| + Label* if_false) {
|
| + Label if_true(this);
|
| + BranchIfNumericRelationalComparison(kLessThan, lhs, rhs, &if_true, if_false);
|
| + Bind(&if_true);
|
| +}
|
| +
|
| compiler::Node* CodeStubAssembler::RelationalComparison(
|
| RelationalComparisonMode mode, compiler::Node* lhs, compiler::Node* rhs,
|
| compiler::Node* context) {
|
| @@ -7490,5 +7642,227 @@ compiler::Node* CodeStubAssembler::InstanceOf(compiler::Node* object,
|
| return result.value();
|
| }
|
|
|
| +compiler::Node* CodeStubAssembler::NumberInc(compiler::Node* value) {
|
| + Variable var_result(this, MachineRepresentation::kTagged),
|
| + var_finc_value(this, MachineRepresentation::kFloat64);
|
| + Label if_issmi(this), if_isnotsmi(this), do_finc(this), end(this);
|
| + Branch(TaggedIsSmi(value), &if_issmi, &if_isnotsmi);
|
| +
|
| + Bind(&if_issmi);
|
| + {
|
| + // Try fast Smi addition first.
|
| + Node* one = SmiConstant(Smi::FromInt(1));
|
| + Node* pair = IntPtrAddWithOverflow(BitcastTaggedToWord(value),
|
| + BitcastTaggedToWord(one));
|
| + Node* overflow = Projection(1, pair);
|
| +
|
| + // Check if the Smi addition overflowed.
|
| + Label if_overflow(this), if_notoverflow(this);
|
| + Branch(overflow, &if_overflow, &if_notoverflow);
|
| +
|
| + Bind(&if_notoverflow);
|
| + var_result.Bind(Projection(0, pair));
|
| + Goto(&end);
|
| +
|
| + Bind(&if_overflow);
|
| + {
|
| + var_finc_value.Bind(SmiToFloat64(value));
|
| + Goto(&do_finc);
|
| + }
|
| + }
|
| +
|
| + Bind(&if_isnotsmi);
|
| + {
|
| + // Check if the value is a HeapNumber.
|
| + Assert(IsHeapNumberMap(LoadMap(value)));
|
| +
|
| + // Load the HeapNumber value.
|
| + var_finc_value.Bind(LoadHeapNumberValue(value));
|
| + Goto(&do_finc);
|
| + }
|
| +
|
| + Bind(&do_finc);
|
| + {
|
| + Node* finc_value = var_finc_value.value();
|
| + Node* one = Float64Constant(1.0);
|
| + Node* finc_result = Float64Add(finc_value, one);
|
| + var_result.Bind(ChangeFloat64ToTagged(finc_result));
|
| + Goto(&end);
|
| + }
|
| +
|
| + Bind(&end);
|
| + return var_result.value();
|
| +}
|
| +
|
| +compiler::Node* CodeStubAssembler::CreateArrayIterator(
|
| + compiler::Node* array, compiler::Node* array_map,
|
| + compiler::Node* array_type, compiler::Node* context, IterationKind mode) {
|
| + int kBaseMapIndex;
|
| + switch (mode) {
|
| + case IterationKind::kKeys:
|
| + kBaseMapIndex = Context::TYPED_ARRAY_KEY_ITERATOR_MAP_INDEX;
|
| + break;
|
| + case IterationKind::kValues:
|
| + kBaseMapIndex = Context::UINT8_ARRAY_VALUE_ITERATOR_MAP_INDEX;
|
| + break;
|
| + case IterationKind::kEntries:
|
| + kBaseMapIndex = Context::UINT8_ARRAY_KEY_VALUE_ITERATOR_MAP_INDEX;
|
| + break;
|
| + }
|
| +
|
| + // Fast Array iterator map index:
|
| + // (kBaseIndex + kFastIteratorOffset) + ElementsKind (for JSArrays)
|
| + // kBaseIndex + (ElementsKind - UINT8_ELEMENTS) (for JSTypedArrays)
|
| + const int kFastIteratorOffset =
|
| + Context::FAST_SMI_ARRAY_VALUE_ITERATOR_MAP_INDEX -
|
| + Context::UINT8_ARRAY_VALUE_ITERATOR_MAP_INDEX;
|
| + STATIC_ASSERT(kFastIteratorOffset ==
|
| + (Context::FAST_SMI_ARRAY_KEY_VALUE_ITERATOR_MAP_INDEX -
|
| + Context::UINT8_ARRAY_KEY_VALUE_ITERATOR_MAP_INDEX));
|
| +
|
| + // Slow Array iterator map index: (kBaseIndex + kSlowIteratorOffset)
|
| + const int kSlowIteratorOffset =
|
| + Context::GENERIC_ARRAY_VALUE_ITERATOR_MAP_INDEX -
|
| + Context::UINT8_ARRAY_VALUE_ITERATOR_MAP_INDEX;
|
| + STATIC_ASSERT(kSlowIteratorOffset ==
|
| + (Context::GENERIC_ARRAY_KEY_VALUE_ITERATOR_MAP_INDEX -
|
| + Context::UINT8_ARRAY_KEY_VALUE_ITERATOR_MAP_INDEX));
|
| +
|
| + // Assert: Type(array) is Object
|
| + Assert(IsJSReceiverInstanceType(array_type));
|
| +
|
| + Variable var_result(this, MachineRepresentation::kTagged);
|
| + Variable var_map_index(this, MachineType::PointerRepresentation());
|
| + Variable var_array_map(this, MachineRepresentation::kTagged);
|
| +
|
| + Label return_result(this);
|
| + Label allocate_iterator(this);
|
| +
|
| + if (mode == IterationKind::kKeys) {
|
| + // There are only two key iterator maps, branch depending on whether or not
|
| + // the receiver is a TypedArray or not.
|
| +
|
| + Label if_isarray(this), if_istypedarray(this), if_isgeneric(this);
|
| + Label* kInstanceTypeHandlers[] = {&if_isarray, &if_istypedarray};
|
| +
|
| + static int32_t kInstanceType[] = {JS_ARRAY_TYPE, JS_TYPED_ARRAY_TYPE};
|
| +
|
| + Switch(array_type, &if_isgeneric, kInstanceType, kInstanceTypeHandlers,
|
| + arraysize(kInstanceType));
|
| +
|
| + Bind(&if_isarray);
|
| + {
|
| + var_map_index.Bind(
|
| + IntPtrConstant(Context::FAST_ARRAY_KEY_ITERATOR_MAP_INDEX));
|
| + var_array_map.Bind(array_map);
|
| + Goto(&allocate_iterator);
|
| + }
|
| +
|
| + Bind(&if_istypedarray);
|
| + {
|
| + var_map_index.Bind(
|
| + IntPtrConstant(Context::TYPED_ARRAY_KEY_ITERATOR_MAP_INDEX));
|
| + var_array_map.Bind(UndefinedConstant());
|
| + Goto(&allocate_iterator);
|
| + }
|
| +
|
| + Bind(&if_isgeneric);
|
| + {
|
| + var_map_index.Bind(
|
| + IntPtrConstant(Context::GENERIC_ARRAY_KEY_ITERATOR_MAP_INDEX));
|
| + var_array_map.Bind(UndefinedConstant());
|
| + Goto(&allocate_iterator);
|
| + }
|
| + } else {
|
| + Label if_istypedarray(this), if_isgeneric(this);
|
| + Branch(Word32Equal(array_type, Int32Constant(JS_TYPED_ARRAY_TYPE)),
|
| + &if_istypedarray, &if_isgeneric);
|
| +
|
| + Bind(&if_isgeneric);
|
| + {
|
| + Label if_isfast(this), if_isslow(this);
|
| + BranchIfFastJSArray(array, context, &if_isfast, &if_isslow);
|
| +
|
| + Bind(&if_isfast);
|
| + {
|
| + Node* map_index =
|
| + IntPtrAdd(IntPtrConstant(kBaseMapIndex + kFastIteratorOffset),
|
| + LoadMapElementsKind(array_map));
|
| + Assert(IntPtrGreaterThanOrEqual(
|
| + map_index, IntPtrConstant(kBaseMapIndex + kFastIteratorOffset)));
|
| + Assert(IntPtrLessThan(
|
| + map_index, IntPtrConstant(kBaseMapIndex + kSlowIteratorOffset)));
|
| +
|
| + var_map_index.Bind(map_index);
|
| + var_array_map.Bind(array_map);
|
| + Goto(&allocate_iterator);
|
| + }
|
| +
|
| + Bind(&if_isslow);
|
| + {
|
| + Node* map_index = IntPtrAdd(IntPtrConstant(kBaseMapIndex),
|
| + IntPtrConstant(kSlowIteratorOffset));
|
| + var_map_index.Bind(map_index);
|
| + var_array_map.Bind(UndefinedConstant());
|
| + Goto(&allocate_iterator);
|
| + }
|
| + }
|
| +
|
| + Bind(&if_istypedarray);
|
| + {
|
| + Node* map_index =
|
| + IntPtrAdd(IntPtrConstant(kBaseMapIndex - UINT8_ELEMENTS),
|
| + LoadMapElementsKind(array_map));
|
| + Assert(IntPtrLessThan(
|
| + map_index, IntPtrConstant(kBaseMapIndex + kFastIteratorOffset)));
|
| + Assert(
|
| + IntPtrGreaterThanOrEqual(map_index, IntPtrConstant(kBaseMapIndex)));
|
| + var_map_index.Bind(map_index);
|
| + var_array_map.Bind(UndefinedConstant());
|
| + Goto(&allocate_iterator);
|
| + }
|
| + }
|
| +
|
| + Bind(&allocate_iterator);
|
| + {
|
| + Node* map =
|
| + LoadFixedArrayElement(LoadNativeContext(context), var_map_index.value(),
|
| + 0, CodeStubAssembler::INTPTR_PARAMETERS);
|
| + var_result.Bind(AllocateJSArrayIterator(array, var_array_map.value(), map));
|
| + Goto(&return_result);
|
| + }
|
| +
|
| + Bind(&return_result);
|
| + return var_result.value();
|
| +}
|
| +
|
| +compiler::Node* CodeStubAssembler::AllocateJSArrayIterator(
|
| + compiler::Node* array, compiler::Node* array_map, compiler::Node* map) {
|
| + Node* iterator = Allocate(JSArrayIterator::kSize);
|
| + StoreMapNoWriteBarrier(iterator, map);
|
| + StoreObjectFieldRoot(iterator, JSArrayIterator::kPropertiesOffset,
|
| + Heap::kEmptyFixedArrayRootIndex);
|
| + StoreObjectFieldRoot(iterator, JSArrayIterator::kElementsOffset,
|
| + Heap::kEmptyFixedArrayRootIndex);
|
| + StoreObjectFieldNoWriteBarrier(iterator,
|
| + JSArrayIterator::kIteratedObjectOffset, array);
|
| + StoreObjectFieldNoWriteBarrier(iterator, JSArrayIterator::kNextIndexOffset,
|
| + SmiConstant(Smi::FromInt(0)));
|
| + StoreObjectFieldNoWriteBarrier(
|
| + iterator, JSArrayIterator::kIteratedObjectMapOffset, array_map);
|
| + return iterator;
|
| +}
|
| +
|
| +compiler::Node* CodeStubAssembler::IsDetachedBuffer(compiler::Node* buffer) {
|
| + AssertInstanceType(buffer, JS_ARRAY_BUFFER_TYPE);
|
| +
|
| + Node* buffer_bit_field = LoadObjectField(
|
| + buffer, JSArrayBuffer::kBitFieldOffset, MachineType::Uint32());
|
| + Node* was_neutered_mask = Int32Constant(JSArrayBuffer::WasNeutered::kMask);
|
| +
|
| + return Word32NotEqual(Word32And(buffer_bit_field, was_neutered_mask),
|
| + Int32Constant(0));
|
| +}
|
| +
|
| } // namespace internal
|
| } // namespace v8
|
|
|