Revert "[builtins] Delete unused TypedArrayInitialize intrinsic."
This reverts commit 5c200fa0f1
.
Reason for revert: Breaks compile:
https://build.chromium.org/p/client.v8/builders/V8%20Linux%20-%20builder/builds/23538
Maybe conflicts with a change that just landed.
Original change's description:
> [builtins] Delete unused TypedArrayInitialize intrinsic.
>
> This CL only deletes code. We dont call these anymore, so they are safe
> to remove.
>
> BUG=v8:5977
>
> Change-Id: I59889c3dbb9c2610f3502d582b6c307b1fb4f63b
> Reviewed-on: https://chromium-review.googlesource.com/448517
> Commit-Queue: Peter Marshall <petermarshall@chromium.org>
> Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#43543}
TBR=cbruni@chromium.org,petermarshall@chromium.org,bmeurer@chromium.org,v8-reviews@googlegroups.com
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
BUG=v8:5977
Change-Id: Iba1611f4c93d105a4163338b59bda42ea7937443
Reviewed-on: https://chromium-review.googlesource.com/448562
Reviewed-by: Michael Achenbach <machenbach@chromium.org>
Commit-Queue: Michael Achenbach <machenbach@chromium.org>
Cr-Commit-Position: refs/heads/master@{#43544}
This commit is contained in:
parent
5c200fa0f1
commit
cb672f4df6
@ -9870,6 +9870,328 @@ void HOptimizedGraphBuilder::BuildInitializeInobjectProperties(
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
HValue* HGraphBuilder::BuildAllocateEmptyArrayBuffer(HValue* byte_length) {
|
||||
// We HForceRepresentation here to avoid allocations during an *-to-tagged
|
||||
// HChange that could cause GC while the array buffer object is not fully
|
||||
// initialized.
|
||||
HObjectAccess byte_length_access(HObjectAccess::ForJSArrayBufferByteLength());
|
||||
byte_length = AddUncasted<HForceRepresentation>(
|
||||
byte_length, byte_length_access.representation());
|
||||
HAllocate* result =
|
||||
BuildAllocate(Add<HConstant>(JSArrayBuffer::kSizeWithInternalFields),
|
||||
HType::JSObject(), JS_ARRAY_BUFFER_TYPE, HAllocationMode());
|
||||
|
||||
HValue* native_context = BuildGetNativeContext();
|
||||
Add<HStoreNamedField>(
|
||||
result, HObjectAccess::ForMap(),
|
||||
Add<HLoadNamedField>(
|
||||
native_context, nullptr,
|
||||
HObjectAccess::ForContextSlot(Context::ARRAY_BUFFER_MAP_INDEX)));
|
||||
|
||||
HConstant* empty_fixed_array =
|
||||
Add<HConstant>(isolate()->factory()->empty_fixed_array());
|
||||
Add<HStoreNamedField>(
|
||||
result, HObjectAccess::ForJSArrayOffset(JSArray::kPropertiesOffset),
|
||||
empty_fixed_array);
|
||||
Add<HStoreNamedField>(
|
||||
result, HObjectAccess::ForJSArrayOffset(JSArray::kElementsOffset),
|
||||
empty_fixed_array);
|
||||
Add<HStoreNamedField>(
|
||||
result, HObjectAccess::ForJSArrayBufferBackingStore().WithRepresentation(
|
||||
Representation::Smi()),
|
||||
graph()->GetConstant0());
|
||||
Add<HStoreNamedField>(result, byte_length_access, byte_length);
|
||||
Add<HStoreNamedField>(result, HObjectAccess::ForJSArrayBufferBitFieldSlot(),
|
||||
graph()->GetConstant0());
|
||||
Add<HStoreNamedField>(
|
||||
result, HObjectAccess::ForJSArrayBufferBitField(),
|
||||
Add<HConstant>((1 << JSArrayBuffer::IsExternal::kShift) |
|
||||
(1 << JSArrayBuffer::IsNeuterable::kShift)));
|
||||
|
||||
for (int field = 0; field < v8::ArrayBuffer::kInternalFieldCount; ++field) {
|
||||
Add<HStoreNamedField>(
|
||||
result,
|
||||
HObjectAccess::ForObservableJSObjectOffset(
|
||||
JSArrayBuffer::kSize + field * kPointerSize, Representation::Smi()),
|
||||
graph()->GetConstant0());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
template <class ViewClass>
|
||||
void HGraphBuilder::BuildArrayBufferViewInitialization(
|
||||
HValue* obj,
|
||||
HValue* buffer,
|
||||
HValue* byte_offset,
|
||||
HValue* byte_length) {
|
||||
|
||||
for (int offset = ViewClass::kSize;
|
||||
offset < ViewClass::kSizeWithInternalFields;
|
||||
offset += kPointerSize) {
|
||||
Add<HStoreNamedField>(obj,
|
||||
HObjectAccess::ForObservableJSObjectOffset(offset),
|
||||
graph()->GetConstant0());
|
||||
}
|
||||
|
||||
Add<HStoreNamedField>(
|
||||
obj,
|
||||
HObjectAccess::ForJSArrayBufferViewByteOffset(),
|
||||
byte_offset);
|
||||
Add<HStoreNamedField>(
|
||||
obj,
|
||||
HObjectAccess::ForJSArrayBufferViewByteLength(),
|
||||
byte_length);
|
||||
Add<HStoreNamedField>(obj, HObjectAccess::ForJSArrayBufferViewBuffer(),
|
||||
buffer);
|
||||
}
|
||||
|
||||
|
||||
HValue* HOptimizedGraphBuilder::BuildAllocateExternalElements(
|
||||
ExternalArrayType array_type,
|
||||
bool is_zero_byte_offset,
|
||||
HValue* buffer, HValue* byte_offset, HValue* length) {
|
||||
Handle<Map> external_array_map(
|
||||
isolate()->heap()->MapForFixedTypedArray(array_type));
|
||||
|
||||
// The HForceRepresentation is to prevent possible deopt on int-smi
|
||||
// conversion after allocation but before the new object fields are set.
|
||||
length = AddUncasted<HForceRepresentation>(length, Representation::Smi());
|
||||
HValue* elements = Add<HAllocate>(
|
||||
Add<HConstant>(FixedTypedArrayBase::kHeaderSize), HType::HeapObject(),
|
||||
NOT_TENURED, external_array_map->instance_type(),
|
||||
graph()->GetConstant0());
|
||||
|
||||
AddStoreMapConstant(elements, external_array_map);
|
||||
Add<HStoreNamedField>(elements,
|
||||
HObjectAccess::ForFixedArrayLength(), length);
|
||||
|
||||
HValue* backing_store = Add<HLoadNamedField>(
|
||||
buffer, nullptr, HObjectAccess::ForJSArrayBufferBackingStore());
|
||||
|
||||
HValue* typed_array_start;
|
||||
if (is_zero_byte_offset) {
|
||||
typed_array_start = backing_store;
|
||||
} else {
|
||||
HInstruction* external_pointer =
|
||||
AddUncasted<HAdd>(backing_store, byte_offset);
|
||||
// Arguments are checked prior to call to TypedArrayInitialize,
|
||||
// including byte_offset.
|
||||
external_pointer->ClearFlag(HValue::kCanOverflow);
|
||||
typed_array_start = external_pointer;
|
||||
}
|
||||
|
||||
Add<HStoreNamedField>(elements,
|
||||
HObjectAccess::ForFixedTypedArrayBaseBasePointer(),
|
||||
graph()->GetConstant0());
|
||||
Add<HStoreNamedField>(elements,
|
||||
HObjectAccess::ForFixedTypedArrayBaseExternalPointer(),
|
||||
typed_array_start);
|
||||
|
||||
return elements;
|
||||
}
|
||||
|
||||
|
||||
HValue* HOptimizedGraphBuilder::BuildAllocateFixedTypedArray(
|
||||
ExternalArrayType array_type, size_t element_size,
|
||||
ElementsKind fixed_elements_kind, HValue* byte_length, HValue* length,
|
||||
bool initialize) {
|
||||
STATIC_ASSERT(
|
||||
(FixedTypedArrayBase::kHeaderSize & kObjectAlignmentMask) == 0);
|
||||
HValue* total_size;
|
||||
|
||||
// if fixed array's elements are not aligned to object's alignment,
|
||||
// we need to align the whole array to object alignment.
|
||||
if (element_size % kObjectAlignment != 0) {
|
||||
total_size = BuildObjectSizeAlignment(
|
||||
byte_length, FixedTypedArrayBase::kHeaderSize);
|
||||
} else {
|
||||
total_size = AddUncasted<HAdd>(byte_length,
|
||||
Add<HConstant>(FixedTypedArrayBase::kHeaderSize));
|
||||
total_size->ClearFlag(HValue::kCanOverflow);
|
||||
}
|
||||
|
||||
// The HForceRepresentation is to prevent possible deopt on int-smi
|
||||
// conversion after allocation but before the new object fields are set.
|
||||
length = AddUncasted<HForceRepresentation>(length, Representation::Smi());
|
||||
Handle<Map> fixed_typed_array_map(
|
||||
isolate()->heap()->MapForFixedTypedArray(array_type));
|
||||
HAllocate* elements = Add<HAllocate>(
|
||||
total_size, HType::HeapObject(), NOT_TENURED,
|
||||
fixed_typed_array_map->instance_type(), graph()->GetConstant0());
|
||||
|
||||
#ifndef V8_HOST_ARCH_64_BIT
|
||||
if (array_type == kExternalFloat64Array) {
|
||||
elements->MakeDoubleAligned();
|
||||
}
|
||||
#endif
|
||||
|
||||
AddStoreMapConstant(elements, fixed_typed_array_map);
|
||||
|
||||
Add<HStoreNamedField>(elements,
|
||||
HObjectAccess::ForFixedArrayLength(),
|
||||
length);
|
||||
Add<HStoreNamedField>(
|
||||
elements, HObjectAccess::ForFixedTypedArrayBaseBasePointer(), elements);
|
||||
|
||||
Add<HStoreNamedField>(
|
||||
elements, HObjectAccess::ForFixedTypedArrayBaseExternalPointer(),
|
||||
Add<HConstant>(ExternalReference::fixed_typed_array_base_data_offset()));
|
||||
|
||||
HValue* filler = Add<HConstant>(static_cast<int32_t>(0));
|
||||
|
||||
if (initialize) {
|
||||
LoopBuilder builder(this, context(), LoopBuilder::kPostIncrement);
|
||||
|
||||
HValue* backing_store = AddUncasted<HAdd>(
|
||||
Add<HConstant>(ExternalReference::fixed_typed_array_base_data_offset()),
|
||||
elements, AddOfExternalAndTagged);
|
||||
|
||||
HValue* key = builder.BeginBody(
|
||||
Add<HConstant>(static_cast<int32_t>(0)),
|
||||
length, Token::LT);
|
||||
Add<HStoreKeyed>(backing_store, key, filler, elements, fixed_elements_kind);
|
||||
|
||||
builder.EndBody();
|
||||
}
|
||||
return elements;
|
||||
}
|
||||
|
||||
|
||||
void HOptimizedGraphBuilder::GenerateTypedArrayInitialize(
|
||||
CallRuntime* expr) {
|
||||
ZoneList<Expression*>* arguments = expr->arguments();
|
||||
|
||||
static const int kObjectArg = 0;
|
||||
static const int kArrayIdArg = 1;
|
||||
static const int kBufferArg = 2;
|
||||
static const int kByteOffsetArg = 3;
|
||||
static const int kByteLengthArg = 4;
|
||||
static const int kInitializeArg = 5;
|
||||
static const int kArgsLength = 6;
|
||||
DCHECK(arguments->length() == kArgsLength);
|
||||
|
||||
|
||||
CHECK_ALIVE(VisitForValue(arguments->at(kObjectArg)));
|
||||
HValue* obj = Pop();
|
||||
|
||||
if (!arguments->at(kArrayIdArg)->IsLiteral()) {
|
||||
// This should never happen in real use, but can happen when fuzzing.
|
||||
// Just bail out.
|
||||
Bailout(kNeedSmiLiteral);
|
||||
return;
|
||||
}
|
||||
Handle<Object> value =
|
||||
static_cast<Literal*>(arguments->at(kArrayIdArg))->value();
|
||||
if (!value->IsSmi()) {
|
||||
// This should never happen in real use, but can happen when fuzzing.
|
||||
// Just bail out.
|
||||
Bailout(kNeedSmiLiteral);
|
||||
return;
|
||||
}
|
||||
int array_id = Smi::cast(*value)->value();
|
||||
|
||||
HValue* buffer;
|
||||
if (!arguments->at(kBufferArg)->IsNullLiteral()) {
|
||||
CHECK_ALIVE(VisitForValue(arguments->at(kBufferArg)));
|
||||
buffer = Pop();
|
||||
} else {
|
||||
buffer = NULL;
|
||||
}
|
||||
|
||||
HValue* byte_offset;
|
||||
bool is_zero_byte_offset;
|
||||
|
||||
if (arguments->at(kByteOffsetArg)->IsLiteral() &&
|
||||
Smi::kZero ==
|
||||
*static_cast<Literal*>(arguments->at(kByteOffsetArg))->value()) {
|
||||
byte_offset = Add<HConstant>(static_cast<int32_t>(0));
|
||||
is_zero_byte_offset = true;
|
||||
} else {
|
||||
CHECK_ALIVE(VisitForValue(arguments->at(kByteOffsetArg)));
|
||||
byte_offset = Pop();
|
||||
is_zero_byte_offset = false;
|
||||
DCHECK(buffer != NULL);
|
||||
}
|
||||
|
||||
CHECK_ALIVE(VisitForValue(arguments->at(kByteLengthArg)));
|
||||
HValue* byte_length = Pop();
|
||||
|
||||
CHECK(arguments->at(kInitializeArg)->IsLiteral());
|
||||
bool initialize = static_cast<Literal*>(arguments->at(kInitializeArg))
|
||||
->value()
|
||||
->BooleanValue();
|
||||
|
||||
NoObservableSideEffectsScope scope(this);
|
||||
IfBuilder byte_offset_smi(this);
|
||||
|
||||
if (!is_zero_byte_offset) {
|
||||
byte_offset_smi.If<HIsSmiAndBranch>(byte_offset);
|
||||
byte_offset_smi.Then();
|
||||
}
|
||||
|
||||
ExternalArrayType array_type =
|
||||
kExternalInt8Array; // Bogus initialization.
|
||||
size_t element_size = 1; // Bogus initialization.
|
||||
ElementsKind fixed_elements_kind = // Bogus initialization.
|
||||
INT8_ELEMENTS;
|
||||
Runtime::ArrayIdToTypeAndSize(array_id,
|
||||
&array_type,
|
||||
&fixed_elements_kind,
|
||||
&element_size);
|
||||
|
||||
|
||||
{ // byte_offset is Smi.
|
||||
HValue* allocated_buffer = buffer;
|
||||
if (buffer == NULL) {
|
||||
allocated_buffer = BuildAllocateEmptyArrayBuffer(byte_length);
|
||||
}
|
||||
BuildArrayBufferViewInitialization<JSTypedArray>(obj, allocated_buffer,
|
||||
byte_offset, byte_length);
|
||||
|
||||
|
||||
HInstruction* length = AddUncasted<HDiv>(byte_length,
|
||||
Add<HConstant>(static_cast<int32_t>(element_size)));
|
||||
// Callers (in typedarray.js) ensure that length <= %_MaxSmi().
|
||||
length = AddUncasted<HForceRepresentation>(length, Representation::Smi());
|
||||
|
||||
Add<HStoreNamedField>(obj,
|
||||
HObjectAccess::ForJSTypedArrayLength(),
|
||||
length);
|
||||
|
||||
HValue* elements;
|
||||
if (buffer != NULL) {
|
||||
elements = BuildAllocateExternalElements(
|
||||
array_type, is_zero_byte_offset, buffer, byte_offset, length);
|
||||
} else {
|
||||
DCHECK(is_zero_byte_offset);
|
||||
elements = BuildAllocateFixedTypedArray(array_type, element_size,
|
||||
fixed_elements_kind, byte_length,
|
||||
length, initialize);
|
||||
}
|
||||
Add<HStoreNamedField>(
|
||||
obj, HObjectAccess::ForElementsPointer(), elements);
|
||||
}
|
||||
|
||||
if (!is_zero_byte_offset) {
|
||||
byte_offset_smi.Else();
|
||||
{ // byte_offset is not Smi.
|
||||
Push(obj);
|
||||
CHECK_ALIVE(VisitForValue(arguments->at(kArrayIdArg)));
|
||||
Push(buffer);
|
||||
Push(byte_offset);
|
||||
Push(byte_length);
|
||||
CHECK_ALIVE(VisitForValue(arguments->at(kInitializeArg)));
|
||||
PushArgumentsFromEnvironment(kArgsLength);
|
||||
Add<HCallRuntime>(expr->function(), kArgsLength);
|
||||
}
|
||||
}
|
||||
byte_offset_smi.End();
|
||||
}
|
||||
|
||||
|
||||
void HOptimizedGraphBuilder::GenerateMaxSmi(CallRuntime* expr) {
|
||||
DCHECK(expr->arguments()->length() == 0);
|
||||
HConstant* max_smi = New<HConstant>(static_cast<int32_t>(Smi::kMaxValue));
|
||||
|
@ -2170,6 +2170,7 @@ class HOptimizedGraphBuilder : public HGraphBuilder,
|
||||
F(SubString) \
|
||||
F(DebugIsActive) \
|
||||
/* Typed Arrays */ \
|
||||
F(TypedArrayInitialize) \
|
||||
F(MaxSmi) \
|
||||
F(TypedArrayMaxSizeInHeap) \
|
||||
F(ArrayBufferViewGetByteLength) \
|
||||
|
@ -61,6 +61,84 @@ void Runtime::ArrayIdToTypeAndSize(int arrayId, ExternalArrayType* array_type,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_TypedArrayInitialize) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK_EQ(6, args.length());
|
||||
CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, holder, 0);
|
||||
CONVERT_SMI_ARG_CHECKED(arrayId, 1);
|
||||
CONVERT_ARG_HANDLE_CHECKED(Object, maybe_buffer, 2);
|
||||
CONVERT_NUMBER_ARG_HANDLE_CHECKED(byte_offset_object, 3);
|
||||
CONVERT_NUMBER_ARG_HANDLE_CHECKED(byte_length_object, 4);
|
||||
CONVERT_BOOLEAN_ARG_CHECKED(initialize, 5);
|
||||
|
||||
CHECK(arrayId >= Runtime::ARRAY_ID_FIRST &&
|
||||
arrayId <= Runtime::ARRAY_ID_LAST);
|
||||
|
||||
ExternalArrayType array_type = kExternalInt8Array; // Bogus initialization.
|
||||
size_t element_size = 1; // Bogus initialization.
|
||||
ElementsKind fixed_elements_kind = INT8_ELEMENTS; // Bogus initialization.
|
||||
Runtime::ArrayIdToTypeAndSize(arrayId, &array_type, &fixed_elements_kind,
|
||||
&element_size);
|
||||
CHECK(holder->map()->elements_kind() == fixed_elements_kind);
|
||||
|
||||
size_t byte_offset = 0;
|
||||
size_t byte_length = 0;
|
||||
CHECK(TryNumberToSize(*byte_offset_object, &byte_offset));
|
||||
CHECK(TryNumberToSize(*byte_length_object, &byte_length));
|
||||
|
||||
if (maybe_buffer->IsJSArrayBuffer()) {
|
||||
Handle<JSArrayBuffer> buffer = Handle<JSArrayBuffer>::cast(maybe_buffer);
|
||||
size_t array_buffer_byte_length = NumberToSize(buffer->byte_length());
|
||||
CHECK(byte_offset <= array_buffer_byte_length);
|
||||
CHECK(array_buffer_byte_length - byte_offset >= byte_length);
|
||||
} else {
|
||||
CHECK(maybe_buffer->IsNull(isolate));
|
||||
}
|
||||
|
||||
CHECK(byte_length % element_size == 0);
|
||||
size_t length = byte_length / element_size;
|
||||
|
||||
if (length > static_cast<unsigned>(Smi::kMaxValue)) {
|
||||
THROW_NEW_ERROR_RETURN_FAILURE(
|
||||
isolate, NewRangeError(MessageTemplate::kInvalidTypedArrayLength));
|
||||
}
|
||||
|
||||
// All checks are done, now we can modify objects.
|
||||
|
||||
DCHECK_EQ(v8::ArrayBufferView::kInternalFieldCount,
|
||||
holder->GetInternalFieldCount());
|
||||
for (int i = 0; i < v8::ArrayBufferView::kInternalFieldCount; i++) {
|
||||
holder->SetInternalField(i, Smi::kZero);
|
||||
}
|
||||
Handle<Object> length_obj = isolate->factory()->NewNumberFromSize(length);
|
||||
holder->set_length(*length_obj);
|
||||
holder->set_byte_offset(*byte_offset_object);
|
||||
holder->set_byte_length(*byte_length_object);
|
||||
|
||||
if (!maybe_buffer->IsNull(isolate)) {
|
||||
Handle<JSArrayBuffer> buffer = Handle<JSArrayBuffer>::cast(maybe_buffer);
|
||||
holder->set_buffer(*buffer);
|
||||
|
||||
Handle<FixedTypedArrayBase> elements =
|
||||
isolate->factory()->NewFixedTypedArrayWithExternalPointer(
|
||||
static_cast<int>(length), array_type,
|
||||
static_cast<uint8_t*>(buffer->backing_store()) + byte_offset);
|
||||
holder->set_elements(*elements);
|
||||
} else {
|
||||
Handle<JSArrayBuffer> buffer = isolate->factory()->NewJSArrayBuffer();
|
||||
JSArrayBuffer::Setup(buffer, isolate, true, NULL, byte_length,
|
||||
SharedFlag::kNotShared);
|
||||
holder->set_buffer(*buffer);
|
||||
Handle<FixedTypedArrayBase> elements =
|
||||
isolate->factory()->NewFixedTypedArray(static_cast<int>(length),
|
||||
array_type, initialize);
|
||||
holder->set_elements(*elements);
|
||||
}
|
||||
return isolate->heap()->undefined_value();
|
||||
}
|
||||
|
||||
|
||||
// Initializes a typed array from an array-like object.
|
||||
// If an array-like object happens to be a typed array of the same type,
|
||||
// initializes backing store using memove.
|
||||
|
@ -615,6 +615,7 @@ namespace internal {
|
||||
#define FOR_EACH_INTRINSIC_TYPEDARRAY(F) \
|
||||
F(ArrayBufferGetByteLength, 1, 1) \
|
||||
F(ArrayBufferNeuter, 1, 1) \
|
||||
F(TypedArrayInitialize, 6, 1) \
|
||||
F(TypedArrayInitializeFromArrayLike, 4, 1) \
|
||||
F(ArrayBufferViewGetByteLength, 1, 1) \
|
||||
F(ArrayBufferViewGetByteOffset, 1, 1) \
|
||||
|
Loading…
Reference in New Issue
Block a user