Commit ddc155d8 authored by Jakob Kummerow's avatar Jakob Kummerow Committed by Commit Bot

[bigint] Add CSA support for Big*64Array stores

Bug: v8:6791
Change-Id: I1423321552e50d9ccb40a94b73f393d6d46fa629
Reviewed-on: https://chromium-review.googlesource.com/927789
Commit-Queue: Jakob Kummerow <jkummerow@chromium.org>
Reviewed-by: 's avatarIgor Sheludko <ishell@chromium.org>
Cr-Commit-Position: refs/heads/master@{#51492}
parent 3ef16185
...@@ -523,11 +523,7 @@ Node* TypedArrayBuiltinsAssembler::LoadDataPtr(Node* typed_array) { ...@@ -523,11 +523,7 @@ Node* TypedArrayBuiltinsAssembler::LoadDataPtr(Node* typed_array) {
CSA_ASSERT(this, IsJSTypedArray(typed_array)); CSA_ASSERT(this, IsJSTypedArray(typed_array));
Node* elements = LoadElements(typed_array); Node* elements = LoadElements(typed_array);
CSA_ASSERT(this, IsFixedTypedArray(elements)); CSA_ASSERT(this, IsFixedTypedArray(elements));
Node* base_pointer = BitcastTaggedToWord( return LoadFixedTypedArrayBackingStore(CAST(elements));
LoadObjectField(elements, FixedTypedArrayBase::kBasePointerOffset));
Node* external_pointer = BitcastTaggedToWord(
LoadObjectField(elements, FixedTypedArrayBase::kExternalPointerOffset));
return IntPtrAdd(base_pointer, external_pointer);
} }
TNode<BoolT> TypedArrayBuiltinsAssembler::ByteLengthIsValid( TNode<BoolT> TypedArrayBuiltinsAssembler::ByteLengthIsValid(
...@@ -1508,14 +1504,14 @@ TF_BUILTIN(TypedArrayPrototypeKeys, TypedArrayBuiltinsAssembler) { ...@@ -1508,14 +1504,14 @@ TF_BUILTIN(TypedArrayPrototypeKeys, TypedArrayBuiltinsAssembler) {
} }
void TypedArrayBuiltinsAssembler::DebugSanityCheckTypedArrayIndex( void TypedArrayBuiltinsAssembler::DebugSanityCheckTypedArrayIndex(
TNode<JSTypedArray> array, SloppyTNode<Smi> index) { TNode<JSTypedArray> array, TNode<IntPtrT> index) {
#ifdef DEBUG #ifdef DEBUG
TNode<JSArrayBuffer> buffer = TNode<JSArrayBuffer> buffer =
LoadObjectField<JSArrayBuffer>(array, JSArrayBufferView::kBufferOffset); LoadObjectField<JSArrayBuffer>(array, JSArrayBufferView::kBufferOffset);
CSA_ASSERT(this, Word32BinaryNot(IsDetachedBuffer(buffer))); CSA_ASSERT(this, Word32BinaryNot(IsDetachedBuffer(buffer)));
TNode<Smi> array_length = TNode<IntPtrT> array_length =
LoadObjectField<Smi>(array, JSTypedArray::kLengthOffset); LoadAndUntagObjectField(array, JSTypedArray::kLengthOffset);
CSA_ASSERT(this, SmiLessThan(index, array_length)); CSA_ASSERT(this, IntPtrLessThan(index, array_length));
#endif #endif
} }
...@@ -1524,15 +1520,13 @@ TF_BUILTIN(TypedArrayOf, TypedArrayBuiltinsAssembler) { ...@@ -1524,15 +1520,13 @@ TF_BUILTIN(TypedArrayOf, TypedArrayBuiltinsAssembler) {
TNode<Context> context = CAST(Parameter(BuiltinDescriptor::kContext)); TNode<Context> context = CAST(Parameter(BuiltinDescriptor::kContext));
// 1. Let len be the actual number of arguments passed to this function. // 1. Let len be the actual number of arguments passed to this function.
TNode<Int32T> argc = TNode<IntPtrT> length = ChangeInt32ToIntPtr(
UncheckedCast<Int32T>(Parameter(BuiltinDescriptor::kArgumentsCount)); UncheckedCast<Int32T>(Parameter(BuiltinDescriptor::kArgumentsCount)));
TNode<Smi> length = SmiFromWord32(argc);
// 2. Let items be the List of arguments passed to this function. // 2. Let items be the List of arguments passed to this function.
CodeStubArguments args(this, length, nullptr, ParameterMode::SMI_PARAMETERS, CodeStubArguments args(this, length, nullptr, INTPTR_PARAMETERS,
CodeStubArguments::ReceiverMode::kHasReceiver); CodeStubArguments::ReceiverMode::kHasReceiver);
Label if_not_constructor(this, Label::kDeferred), Label if_not_constructor(this, Label::kDeferred);
unreachable(this, Label::kDeferred);
// 3. Let C be the this value. // 3. Let C be the this value.
// 4. If IsConstructor(C) is false, throw a TypeError exception. // 4. If IsConstructor(C) is false, throw a TypeError exception.
...@@ -1542,7 +1536,7 @@ TF_BUILTIN(TypedArrayOf, TypedArrayBuiltinsAssembler) { ...@@ -1542,7 +1536,7 @@ TF_BUILTIN(TypedArrayOf, TypedArrayBuiltinsAssembler) {
// 5. Let newObj be ? TypedArrayCreate(C, len). // 5. Let newObj be ? TypedArrayCreate(C, len).
TNode<JSTypedArray> new_typed_array = TNode<JSTypedArray> new_typed_array =
CreateByLength(context, receiver, length, "%TypedArray%.of"); CreateByLength(context, receiver, SmiTag(length), "%TypedArray%.of");
TNode<Word32T> elements_kind = LoadElementsKind(new_typed_array); TNode<Word32T> elements_kind = LoadElementsKind(new_typed_array);
...@@ -1555,43 +1549,38 @@ TF_BUILTIN(TypedArrayOf, TypedArrayBuiltinsAssembler) { ...@@ -1555,43 +1549,38 @@ TF_BUILTIN(TypedArrayOf, TypedArrayBuiltinsAssembler) {
DispatchTypedArrayByElementsKind( DispatchTypedArrayByElementsKind(
elements_kind, elements_kind,
[&](ElementsKind kind, int size, int typed_array_fun_index) { [&](ElementsKind kind, int size, int typed_array_fun_index) {
TNode<FixedTypedArrayBase> elements =
CAST(LoadElements(new_typed_array));
BuildFastLoop( BuildFastLoop(
SmiConstant(0), length, IntPtrConstant(0), length,
[&](Node* index) { [&](Node* index) {
TNode<Object> item = TNode<Object> item = args.AtIndex(index, INTPTR_PARAMETERS);
args.AtIndex(index, ParameterMode::SMI_PARAMETERS); TNode<IntPtrT> intptr_index = UncheckedCast<IntPtrT>(index);
if (kind == BIGINT64_ELEMENTS || kind == BIGUINT64_ELEMENTS) { if (kind == BIGINT64_ELEMENTS || kind == BIGUINT64_ELEMENTS) {
// TODO(jkummerow): Add inline support. EmitBigTypedArrayElementStore(
CallRuntime(Runtime::kSetProperty, context, new_typed_array, new_typed_array, elements, intptr_index, item, context,
index, item, SmiConstant(LanguageMode::kSloppy)); nullptr /* no need to check for neutered buffer */);
} else { } else {
TNode<Number> number = ToNumber_Inline(context, item); Node* value =
PrepareValueForWriteToTypedArray(item, kind, context);
// ToNumber may execute JavaScript code, but it cannot access
// arguments array and new typed array.
DebugSanityCheckTypedArrayIndex(new_typed_array, index);
// Since we can guarantee that "number" is Number type,
// PrepareValueForWriteToTypedArray cannot bail out.
Node* value = PrepareValueForWriteToTypedArray(number, kind,
&unreachable);
// GC may move backing store in ToNumber, thus load backing // GC may move backing store in ToNumber, thus load backing
// store everytime in this loop. // store everytime in this loop.
TNode<IntPtrT> backing_store = TNode<RawPtrT> backing_store =
UncheckedCast<IntPtrT>(LoadDataPtr(new_typed_array)); LoadFixedTypedArrayBackingStore(elements);
StoreElement(backing_store, kind, index, value, SMI_PARAMETERS); StoreElement(backing_store, kind, index, value,
INTPTR_PARAMETERS);
} }
// ToNumber/ToBigInt may execute JavaScript code, but they cannot
// access arguments array and new typed array.
DebugSanityCheckTypedArrayIndex(new_typed_array, intptr_index);
}, },
1, ParameterMode::SMI_PARAMETERS, IndexAdvanceMode::kPost); 1, ParameterMode::INTPTR_PARAMETERS, IndexAdvanceMode::kPost);
}); });
// 8. Return newObj. // 8. Return newObj.
args.PopAndReturn(new_typed_array); args.PopAndReturn(new_typed_array);
BIND(&unreachable);
Unreachable();
BIND(&if_not_constructor); BIND(&if_not_constructor);
ThrowTypeError(context, MessageTemplate::kNotConstructor, receiver); ThrowTypeError(context, MessageTemplate::kNotConstructor, receiver);
} }
...@@ -1668,8 +1657,7 @@ TF_BUILTIN(TypedArrayFrom, TypedArrayBuiltinsAssembler) { ...@@ -1668,8 +1657,7 @@ TF_BUILTIN(TypedArrayFrom, TypedArrayBuiltinsAssembler) {
slow_path(this), create_typed_array(this), slow_path(this), create_typed_array(this),
if_not_constructor(this, Label::kDeferred), if_not_constructor(this, Label::kDeferred),
if_map_fn_not_callable(this, Label::kDeferred), if_map_fn_not_callable(this, Label::kDeferred),
if_iterator_fn_not_callable(this, Label::kDeferred), if_iterator_fn_not_callable(this, Label::kDeferred);
unreachable(this, Label::kDeferred);
CodeStubArguments args( CodeStubArguments args(
this, ChangeInt32ToIntPtr(Parameter(BuiltinDescriptor::kArgumentsCount))); this, ChangeInt32ToIntPtr(Parameter(BuiltinDescriptor::kArgumentsCount)));
...@@ -1784,45 +1772,41 @@ TF_BUILTIN(TypedArrayFrom, TypedArrayBuiltinsAssembler) { ...@@ -1784,45 +1772,41 @@ TF_BUILTIN(TypedArrayFrom, TypedArrayBuiltinsAssembler) {
TNode<Word32T> elements_kind = LoadElementsKind(target_obj.value()); TNode<Word32T> elements_kind = LoadElementsKind(target_obj.value());
// 7e/13 : Copy the elements // 7e/13 : Copy the elements
TNode<FixedTypedArrayBase> elements = CAST(LoadElements(target_obj.value()));
BuildFastLoop( BuildFastLoop(
SmiConstant(0), final_length.value(), SmiConstant(0), final_length.value(),
[&](Node* index) { [&](Node* index) {
TNode<String> const index_string = NumberToString(CAST(index));
TNode<Object> const k_value = TNode<Object> const k_value =
CAST(GetProperty(context, final_source.value(), index_string)); CAST(GetProperty(context, final_source.value(), index));
TNode<Object> const mapped_value = TNode<Object> const mapped_value =
CAST(CallJS(CodeFactory::Call(isolate()), context, map_fn, this_arg, CAST(CallJS(CodeFactory::Call(isolate()), context, map_fn, this_arg,
k_value, index)); k_value, index));
TNode<Number> const number_value = TNode<IntPtrT> intptr_index = SmiUntag(index);
ToNumber_Inline(context, mapped_value);
// map_fn or ToNumber could have executed JavaScript code, but
// they could not have accessed the new typed array.
DebugSanityCheckTypedArrayIndex(target_obj.value(), index);
DispatchTypedArrayByElementsKind( DispatchTypedArrayByElementsKind(
elements_kind, elements_kind,
[&](ElementsKind kind, int size, int typed_array_fun_index) { [&](ElementsKind kind, int size, int typed_array_fun_index) {
if (kind == BIGINT64_ELEMENTS || kind == BIGUINT64_ELEMENTS) { if (kind == BIGINT64_ELEMENTS || kind == BIGUINT64_ELEMENTS) {
// TODO(jkummerow): Add inline support. EmitBigTypedArrayElementStore(
CallRuntime(Runtime::kSetProperty, context, target_obj.value(), target_obj.value(), elements, intptr_index, mapped_value,
index, number_value, context,
SmiConstant(LanguageMode::kSloppy)); nullptr /* no need to check for neutered buffer */);
} else { } else {
// Since we can guarantee that "number_value" is Number type,
// PrepareValueForWriteToTypedArray cannot bail out.
Node* const final_value = PrepareValueForWriteToTypedArray( Node* const final_value = PrepareValueForWriteToTypedArray(
number_value, kind, &unreachable); mapped_value, kind, context);
// GC may move backing store in map_fn, thus load backing // GC may move backing store in map_fn, thus load backing
// store in each iteration of this loop. // store in each iteration of this loop.
TNode<IntPtrT> const backing_store = TNode<RawPtrT> backing_store =
UncheckedCast<IntPtrT>(LoadDataPtr(target_obj.value())); LoadFixedTypedArrayBackingStore(elements);
StoreElement(backing_store, kind, index, final_value, StoreElement(backing_store, kind, index, final_value,
SMI_PARAMETERS); SMI_PARAMETERS);
} }
}); });
// map_fn or ToNumber or ToBigint could have executed JavaScript code,
// but they could not have accessed the new typed array.
DebugSanityCheckTypedArrayIndex(target_obj.value(), intptr_index);
}, },
1, ParameterMode::SMI_PARAMETERS, IndexAdvanceMode::kPost); 1, ParameterMode::SMI_PARAMETERS, IndexAdvanceMode::kPost);
...@@ -1836,9 +1820,6 @@ TF_BUILTIN(TypedArrayFrom, TypedArrayBuiltinsAssembler) { ...@@ -1836,9 +1820,6 @@ TF_BUILTIN(TypedArrayFrom, TypedArrayBuiltinsAssembler) {
BIND(&if_iterator_fn_not_callable); BIND(&if_iterator_fn_not_callable);
ThrowTypeError(context, MessageTemplate::kIteratorSymbolNonCallable); ThrowTypeError(context, MessageTemplate::kIteratorSymbolNonCallable);
BIND(&unreachable);
Unreachable();
} }
// ES %TypedArray%.prototype.filter // ES %TypedArray%.prototype.filter
......
...@@ -127,7 +127,7 @@ class TypedArrayBuiltinsAssembler : public CodeStubAssembler { ...@@ -127,7 +127,7 @@ class TypedArrayBuiltinsAssembler : public CodeStubAssembler {
TNode<Word32T> elements_kind, const TypedArraySwitchCase& case_function); TNode<Word32T> elements_kind, const TypedArraySwitchCase& case_function);
void DebugSanityCheckTypedArrayIndex(TNode<JSTypedArray> array, void DebugSanityCheckTypedArrayIndex(TNode<JSTypedArray> array,
SloppyTNode<Smi> index); TNode<IntPtrT> index);
}; };
} // namespace internal } // namespace internal
......
...@@ -1700,6 +1700,18 @@ Node* CodeStubAssembler::LoadFixedArrayElement(Node* object, Node* index_node, ...@@ -1700,6 +1700,18 @@ Node* CodeStubAssembler::LoadFixedArrayElement(Node* object, Node* index_node,
return Load(MachineType::AnyTagged(), object, offset); return Load(MachineType::AnyTagged(), object, offset);
} }
TNode<RawPtrT> CodeStubAssembler::LoadFixedTypedArrayBackingStore(
TNode<FixedTypedArrayBase> typed_array) {
// Backing store = external_pointer + base_pointer.
Node* external_pointer =
LoadObjectField(typed_array, FixedTypedArrayBase::kExternalPointerOffset,
MachineType::Pointer());
Node* base_pointer =
LoadObjectField(typed_array, FixedTypedArrayBase::kBasePointerOffset);
return UncheckedCast<RawPtrT>(
IntPtrAdd(external_pointer, BitcastTaggedToWord(base_pointer)));
}
Node* CodeStubAssembler::LoadFixedTypedArrayElement( Node* CodeStubAssembler::LoadFixedTypedArrayElement(
Node* data_pointer, Node* index_node, ElementsKind elements_kind, Node* data_pointer, Node* index_node, ElementsKind elements_kind,
ParameterMode parameter_mode) { ParameterMode parameter_mode) {
...@@ -2437,6 +2449,18 @@ void CodeStubAssembler::StoreBigIntDigit(TNode<BigInt> bigint, int digit_index, ...@@ -2437,6 +2449,18 @@ void CodeStubAssembler::StoreBigIntDigit(TNode<BigInt> bigint, int digit_index,
UintPtrT::kMachineRepresentation); UintPtrT::kMachineRepresentation);
} }
TNode<WordT> CodeStubAssembler::LoadBigIntBitfield(TNode<BigInt> bigint) {
return UncheckedCast<WordT>(
LoadObjectField(bigint, BigInt::kBitfieldOffset, MachineType::UintPtr()));
}
TNode<UintPtrT> CodeStubAssembler::LoadBigIntDigit(TNode<BigInt> bigint,
int digit_index) {
return UncheckedCast<UintPtrT>(LoadObjectField(
bigint, BigInt::kDigitsOffset + digit_index * kPointerSize,
MachineType::UintPtr()));
}
Node* CodeStubAssembler::AllocateSeqOneByteString(int length, Node* CodeStubAssembler::AllocateSeqOneByteString(int length,
AllocationFlags flags) { AllocationFlags flags) {
Comment("AllocateSeqOneByteString"); Comment("AllocateSeqOneByteString");
...@@ -5819,7 +5843,7 @@ TNode<Number> CodeStubAssembler::ToNumber_Inline(SloppyTNode<Context> context, ...@@ -5819,7 +5843,7 @@ TNode<Number> CodeStubAssembler::ToNumber_Inline(SloppyTNode<Context> context,
var_result = Select<Number>( var_result = Select<Number>(
IsHeapNumber(input), [=] { return CAST(input); }, IsHeapNumber(input), [=] { return CAST(input); },
[=] { [=] {
return CallBuiltin(Builtins::kNonNumberToNumeric, context, input); return CallBuiltin(Builtins::kNonNumberToNumber, context, input);
}, },
MachineRepresentation::kTagged); MachineRepresentation::kTagged);
Goto(&end); Goto(&end);
...@@ -7871,23 +7895,23 @@ Node* CodeStubAssembler::LoadReceiverMap(Node* receiver) { ...@@ -7871,23 +7895,23 @@ Node* CodeStubAssembler::LoadReceiverMap(Node* receiver) {
MachineRepresentation::kTagged); MachineRepresentation::kTagged);
} }
Node* CodeStubAssembler::TryToIntptr(Node* key, Label* miss) { TNode<IntPtrT> CodeStubAssembler::TryToIntptr(Node* key, Label* miss) {
VARIABLE(var_intptr_key, MachineType::PointerRepresentation()); TVARIABLE(IntPtrT, var_intptr_key);
Label done(this, &var_intptr_key), key_is_smi(this); Label done(this, &var_intptr_key), key_is_smi(this);
GotoIf(TaggedIsSmi(key), &key_is_smi); GotoIf(TaggedIsSmi(key), &key_is_smi);
// Try to convert a heap number to a Smi. // Try to convert a heap number to a Smi.
GotoIfNot(IsHeapNumber(key), miss); GotoIfNot(IsHeapNumber(key), miss);
{ {
Node* value = LoadHeapNumberValue(key); TNode<Float64T> value = LoadHeapNumberValue(key);
Node* int_value = RoundFloat64ToInt32(value); TNode<Int32T> int_value = RoundFloat64ToInt32(value);
GotoIfNot(Float64Equal(value, ChangeInt32ToFloat64(int_value)), miss); GotoIfNot(Float64Equal(value, ChangeInt32ToFloat64(int_value)), miss);
var_intptr_key.Bind(ChangeInt32ToIntPtr(int_value)); var_intptr_key = ChangeInt32ToIntPtr(int_value);
Goto(&done); Goto(&done);
} }
BIND(&key_is_smi); BIND(&key_is_smi);
{ {
var_intptr_key.Bind(SmiUntag(key)); var_intptr_key = SmiUntag(key);
Goto(&done); Goto(&done);
} }
...@@ -8084,7 +8108,7 @@ Node* CodeStubAssembler::Float64ToUint8Clamped(Node* float64_value) { ...@@ -8084,7 +8108,7 @@ Node* CodeStubAssembler::Float64ToUint8Clamped(Node* float64_value) {
} }
Node* CodeStubAssembler::PrepareValueForWriteToTypedArray( Node* CodeStubAssembler::PrepareValueForWriteToTypedArray(
Node* input, ElementsKind elements_kind, Label* bailout) { TNode<Object> input, ElementsKind elements_kind, TNode<Context> context) {
DCHECK(IsFixedTypedArrayElementsKind(elements_kind)); DCHECK(IsFixedTypedArrayElementsKind(elements_kind));
MachineRepresentation rep; MachineRepresentation rep;
...@@ -8109,18 +8133,24 @@ Node* CodeStubAssembler::PrepareValueForWriteToTypedArray( ...@@ -8109,18 +8133,24 @@ Node* CodeStubAssembler::PrepareValueForWriteToTypedArray(
} }
VARIABLE(var_result, rep); VARIABLE(var_result, rep);
Label done(this, &var_result), if_smi(this), if_heapnumber(this); VARIABLE(var_input, MachineRepresentation::kTagged, input);
GotoIf(TaggedIsSmi(input), &if_smi); Label done(this, &var_result), if_smi(this), if_heapnumber_or_oddball(this),
convert(this), loop(this, &var_input);
Goto(&loop);
BIND(&loop);
GotoIf(TaggedIsSmi(var_input.value()), &if_smi);
// We can handle both HeapNumber and Oddball here, since Oddball has the // We can handle both HeapNumber and Oddball here, since Oddball has the
// same layout as the HeapNumber for the HeapNumber::value field. This // same layout as the HeapNumber for the HeapNumber::value field. This
// way we can also properly optimize stores of oddballs to typed arrays. // way we can also properly optimize stores of oddballs to typed arrays.
GotoIf(IsHeapNumber(input), &if_heapnumber); GotoIf(IsHeapNumber(var_input.value()), &if_heapnumber_or_oddball);
STATIC_ASSERT(HeapNumber::kValueOffset == Oddball::kToNumberRawOffset); STATIC_ASSERT(HeapNumber::kValueOffset == Oddball::kToNumberRawOffset);
Branch(HasInstanceType(input, ODDBALL_TYPE), &if_heapnumber, bailout); Branch(HasInstanceType(var_input.value(), ODDBALL_TYPE),
&if_heapnumber_or_oddball, &convert);
BIND(&if_heapnumber); BIND(&if_heapnumber_or_oddball);
{ {
Node* value = LoadHeapNumberValue(input); Node* value = UncheckedCast<Float64T>(LoadObjectField(
var_input.value(), HeapNumber::kValueOffset, MachineType::Float64()));
if (rep == MachineRepresentation::kWord32) { if (rep == MachineRepresentation::kWord32) {
if (elements_kind == UINT8_CLAMPED_ELEMENTS) { if (elements_kind == UINT8_CLAMPED_ELEMENTS) {
value = Float64ToUint8Clamped(value); value = Float64ToUint8Clamped(value);
...@@ -8138,7 +8168,7 @@ Node* CodeStubAssembler::PrepareValueForWriteToTypedArray( ...@@ -8138,7 +8168,7 @@ Node* CodeStubAssembler::PrepareValueForWriteToTypedArray(
BIND(&if_smi); BIND(&if_smi);
{ {
Node* value = SmiToWord32(input); Node* value = SmiToWord32(var_input.value());
if (rep == MachineRepresentation::kFloat32) { if (rep == MachineRepresentation::kFloat32) {
value = RoundInt32ToFloat32(value); value = RoundInt32ToFloat32(value);
} else if (rep == MachineRepresentation::kFloat64) { } else if (rep == MachineRepresentation::kFloat64) {
...@@ -8153,10 +8183,69 @@ Node* CodeStubAssembler::PrepareValueForWriteToTypedArray( ...@@ -8153,10 +8183,69 @@ Node* CodeStubAssembler::PrepareValueForWriteToTypedArray(
Goto(&done); Goto(&done);
} }
BIND(&convert);
{
var_input.Bind(CallBuiltin(Builtins::kNonNumberToNumber, context, input));
Goto(&loop);
}
BIND(&done); BIND(&done);
return var_result.value(); return var_result.value();
} }
void CodeStubAssembler::EmitBigTypedArrayElementStore(
TNode<JSTypedArray> object, TNode<FixedTypedArrayBase> elements,
TNode<IntPtrT> intptr_key, TNode<Object> value, TNode<Context> context,
Label* opt_if_neutered) {
TNode<BigInt> bigint_value = ToBigInt(context, value);
TNode<WordT> bitfield = LoadBigIntBitfield(bigint_value);
TNode<UintPtrT> length = DecodeWord<BigIntBase::LengthBits>(bitfield);
TNode<UintPtrT> sign = DecodeWord<BigIntBase::SignBits>(bitfield);
TVARIABLE(UintPtrT, var_low, Unsigned(IntPtrConstant(0)));
// Only used on 32-bit platforms.
TVARIABLE(UintPtrT, var_high, Unsigned(IntPtrConstant(0)));
Label do_store(this);
GotoIf(WordEqual(length, IntPtrConstant(0)), &do_store);
var_low = LoadBigIntDigit(bigint_value, 0);
if (!Is64()) {
Label load_done(this);
GotoIf(WordEqual(length, IntPtrConstant(1)), &load_done);
var_high = LoadBigIntDigit(bigint_value, 1);
Goto(&load_done);
BIND(&load_done);
}
GotoIf(WordEqual(sign, IntPtrConstant(0)), &do_store);
// Negative value. Simulate two's complement.
if (!Is64()) {
var_high = Unsigned(IntPtrSub(IntPtrConstant(0), var_high.value()));
Label no_carry(this);
GotoIf(WordEqual(var_low.value(), IntPtrConstant(0)), &no_carry);
var_high = Unsigned(IntPtrSub(var_high.value(), IntPtrConstant(1)));
Goto(&no_carry);
BIND(&no_carry);
}
var_low = Unsigned(IntPtrSub(IntPtrConstant(0), var_low.value()));
Goto(&do_store);
BIND(&do_store);
if (opt_if_neutered != nullptr) {
// Check if buffer has been neutered.
Node* buffer = LoadObjectField(object, JSArrayBufferView::kBufferOffset);
GotoIf(IsDetachedBuffer(buffer), opt_if_neutered);
}
Node* backing_store = LoadFixedTypedArrayBackingStore(elements);
Node* offset = ElementOffsetFromIndex(intptr_key, BIGINT64_ELEMENTS,
INTPTR_PARAMETERS, 0);
MachineRepresentation rep = WordT::kMachineRepresentation;
StoreNoWriteBarrier(rep, backing_store, offset, var_low.value());
if (!Is64()) {
StoreNoWriteBarrier(rep, backing_store,
IntPtrAdd(offset, IntPtrConstant(kPointerSize)),
var_high.value());
}
}
void CodeStubAssembler::EmitElementStore(Node* object, Node* key, Node* value, void CodeStubAssembler::EmitElementStore(Node* object, Node* key, Node* value,
bool is_jsarray, bool is_jsarray,
ElementsKind elements_kind, ElementsKind elements_kind,
...@@ -8173,31 +8262,10 @@ void CodeStubAssembler::EmitElementStore(Node* object, Node* key, Node* value, ...@@ -8173,31 +8262,10 @@ void CodeStubAssembler::EmitElementStore(Node* object, Node* key, Node* value,
// TODO(ishell): introduce TryToIntPtrOrSmi() and use OptimalParameterMode(). // TODO(ishell): introduce TryToIntPtrOrSmi() and use OptimalParameterMode().
ParameterMode parameter_mode = INTPTR_PARAMETERS; ParameterMode parameter_mode = INTPTR_PARAMETERS;
Node* intptr_key = TryToIntptr(key, bailout); TNode<IntPtrT> intptr_key = TryToIntptr(key, bailout);
if (IsFixedTypedArrayElementsKind(elements_kind)) { if (IsFixedTypedArrayElementsKind(elements_kind)) {
if (elements_kind == BIGINT64_ELEMENTS ||
elements_kind == BIGUINT64_ELEMENTS) {
// TODO(jkummerow): Add inline support.
CallRuntime(Runtime::kSetProperty, context, object, key, value,
SmiConstant(LanguageMode::kSloppy));
return;
}
Label done(this); Label done(this);
// TODO(ishell): call ToNumber() on value and don't bailout but be careful
// to call it only once if we decide to bailout because of bounds checks.
value = PrepareValueForWriteToTypedArray(value, elements_kind, bailout);
// There must be no allocations between the buffer load and
// and the actual store to backing store, because GC may decide that
// the buffer is not alive or move the elements.
// TODO(ishell): introduce DisallowHeapAllocationCode scope here.
// Check if buffer has been neutered.
Node* buffer = LoadObjectField(object, JSArrayBufferView::kBufferOffset);
GotoIf(IsDetachedBuffer(buffer), bailout);
// Bounds check. // Bounds check.
Node* length = TaggedToParameter( Node* length = TaggedToParameter(
CAST(LoadObjectField(object, JSTypedArray::kLengthOffset)), CAST(LoadObjectField(object, JSTypedArray::kLengthOffset)),
...@@ -8212,16 +8280,28 @@ void CodeStubAssembler::EmitElementStore(Node* object, Node* key, Node* value, ...@@ -8212,16 +8280,28 @@ void CodeStubAssembler::EmitElementStore(Node* object, Node* key, Node* value,
GotoIfNot(UintPtrLessThan(intptr_key, length), bailout); GotoIfNot(UintPtrLessThan(intptr_key, length), bailout);
} }
// Backing store = external_pointer + base_pointer. TNode<Object> value_obj = UncheckedCast<Object>(value);
Node* external_pointer = if (elements_kind == BIGINT64_ELEMENTS ||
LoadObjectField(elements, FixedTypedArrayBase::kExternalPointerOffset, elements_kind == BIGUINT64_ELEMENTS) {
MachineType::Pointer()); EmitBigTypedArrayElementStore(CAST(object), CAST(elements), intptr_key,
Node* base_pointer = value_obj, CAST(context), bailout);
LoadObjectField(elements, FixedTypedArrayBase::kBasePointerOffset); } else {
Node* backing_store = value = PrepareValueForWriteToTypedArray(value_obj, elements_kind,
IntPtrAdd(external_pointer, BitcastTaggedToWord(base_pointer)); CAST(context));
StoreElement(backing_store, elements_kind, intptr_key, value,
parameter_mode); // There must be no allocations between the buffer load and
// and the actual store to backing store, because GC may decide that
// the buffer is not alive or move the elements.
// TODO(ishell): introduce DisallowHeapAllocationCode scope here.
// Check if buffer has been neutered.
Node* buffer = LoadObjectField(object, JSArrayBufferView::kBufferOffset);
GotoIf(IsDetachedBuffer(buffer), bailout);
Node* backing_store = LoadFixedTypedArrayBackingStore(CAST(elements));
StoreElement(backing_store, elements_kind, intptr_key, value,
parameter_mode);
}
Goto(&done); Goto(&done);
BIND(&done); BIND(&done);
......
...@@ -632,6 +632,8 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler { ...@@ -632,6 +632,8 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
Node* LoadDoubleWithHoleCheck( Node* LoadDoubleWithHoleCheck(
Node* base, Node* offset, Label* if_hole, Node* base, Node* offset, Label* if_hole,
MachineType machine_type = MachineType::Float64()); MachineType machine_type = MachineType::Float64());
TNode<RawPtrT> LoadFixedTypedArrayBackingStore(
TNode<FixedTypedArrayBase> typed_array);
Node* LoadFixedTypedArrayElement( Node* LoadFixedTypedArrayElement(
Node* data_pointer, Node* index_node, ElementsKind elements_kind, Node* data_pointer, Node* index_node, ElementsKind elements_kind,
ParameterMode parameter_mode = INTPTR_PARAMETERS); ParameterMode parameter_mode = INTPTR_PARAMETERS);
...@@ -760,6 +762,8 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler { ...@@ -760,6 +762,8 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
void StoreBigIntBitfield(TNode<BigInt> bigint, TNode<WordT> bitfield); void StoreBigIntBitfield(TNode<BigInt> bigint, TNode<WordT> bitfield);
void StoreBigIntDigit(TNode<BigInt> bigint, int digit_index, void StoreBigIntDigit(TNode<BigInt> bigint, int digit_index,
TNode<UintPtrT> digit); TNode<UintPtrT> digit);
TNode<WordT> LoadBigIntBitfield(TNode<BigInt> bigint);
TNode<UintPtrT> LoadBigIntDigit(TNode<BigInt> bigint, int digit_index);
// Allocate a SeqOneByteString with the given length. // Allocate a SeqOneByteString with the given length.
Node* AllocateSeqOneByteString(int length, AllocationFlags flags = kNone); Node* AllocateSeqOneByteString(int length, AllocationFlags flags = kNone);
Node* AllocateSeqOneByteString(Node* context, TNode<Smi> length, Node* AllocateSeqOneByteString(Node* context, TNode<Smi> length,
...@@ -1837,13 +1841,21 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler { ...@@ -1837,13 +1841,21 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
Node* Int32ToUint8Clamped(Node* int32_value); Node* Int32ToUint8Clamped(Node* int32_value);
Node* Float64ToUint8Clamped(Node* float64_value); Node* Float64ToUint8Clamped(Node* float64_value);
Node* PrepareValueForWriteToTypedArray(Node* key, ElementsKind elements_kind, Node* PrepareValueForWriteToTypedArray(TNode<Object> input,
Label* bailout); ElementsKind elements_kind,
TNode<Context> context);
// Store value to an elements array with given elements kind. // Store value to an elements array with given elements kind.
void StoreElement(Node* elements, ElementsKind kind, Node* index, Node* value, void StoreElement(Node* elements, ElementsKind kind, Node* index, Node* value,
ParameterMode mode); ParameterMode mode);
void EmitBigTypedArrayElementStore(TNode<JSTypedArray> object,
TNode<FixedTypedArrayBase> elements,
TNode<IntPtrT> intptr_key,
TNode<Object> value,
TNode<Context> context,
Label* opt_if_neutered);
void EmitElementStore(Node* object, Node* key, Node* value, bool is_jsarray, void EmitElementStore(Node* object, Node* key, Node* value, bool is_jsarray,
ElementsKind elements_kind, ElementsKind elements_kind,
KeyedAccessStoreMode store_mode, Label* bailout, KeyedAccessStoreMode store_mode, Label* bailout,
...@@ -2052,7 +2064,7 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler { ...@@ -2052,7 +2064,7 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
Node* receiver, Label* if_bailout, Node* receiver, Label* if_bailout,
GetOwnPropertyMode mode = kCallJSGetter); GetOwnPropertyMode mode = kCallJSGetter);
Node* TryToIntptr(Node* key, Label* miss); TNode<IntPtrT> TryToIntptr(Node* key, Label* miss);
void BranchIfPrototypesHaveNoElements(Node* receiver_map, void BranchIfPrototypesHaveNoElements(Node* receiver_map,
Label* definitely_no_elements, Label* definitely_no_elements,
......
...@@ -1614,14 +1614,7 @@ void AccessorAssembler::EmitElementLoad( ...@@ -1614,14 +1614,7 @@ void AccessorAssembler::EmitElementLoad(
SmiUntag(CAST(LoadObjectField(object, JSTypedArray::kLengthOffset))); SmiUntag(CAST(LoadObjectField(object, JSTypedArray::kLengthOffset)));
GotoIfNot(UintPtrLessThan(intptr_index, length), out_of_bounds); GotoIfNot(UintPtrLessThan(intptr_index, length), out_of_bounds);
// Backing store = external_pointer + base_pointer. Node* backing_store = LoadFixedTypedArrayBackingStore(CAST(elements));
Node* external_pointer =
LoadObjectField(elements, FixedTypedArrayBase::kExternalPointerOffset,
MachineType::Pointer());
Node* base_pointer =
LoadObjectField(elements, FixedTypedArrayBase::kBasePointerOffset);
Node* backing_store =
IntPtrAdd(external_pointer, BitcastTaggedToWord(base_pointer));
Label uint8_elements(this), int8_elements(this), uint16_elements(this), Label uint8_elements(this), int8_elements(this), uint16_elements(this),
int16_elements(this), uint32_elements(this), int32_elements(this), int16_elements(this), uint32_elements(this), int32_elements(this),
......
...@@ -106,6 +106,8 @@ test_both(function from(BigArray) { ...@@ -106,6 +106,8 @@ test_both(function from(BigArray) {
assertThrows(() => BigArray.from([4, 5]), TypeError); assertThrows(() => BigArray.from([4, 5]), TypeError);
var c = BigArray.from([6, 7], BigInt); var c = BigArray.from([6, 7], BigInt);
assertArrayEquals([6n, 7n], c); assertArrayEquals([6n, 7n], c);
assertThrows(() => Int32Array.from([4n, 5n]), TypeError);
assertThrows(() => Int32Array.from([4, 5], BigInt), TypeError);
}); });
test(function from_mixed() { test(function from_mixed() {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment