5 #include "src/objects/js-array-buffer.h" 6 #include "src/objects/js-array-buffer-inl.h" 8 #include "src/counters.h" 9 #include "src/property-descriptor.h" 16 bool CanonicalNumericIndexString(Isolate* isolate, Handle<Object> s,
17 Handle<Object>* index) {
18 DCHECK(s->IsString() || s->IsSmi());
20 Handle<Object> result;
24 result = String::ToNumber(isolate, Handle<String>::cast(s));
25 if (!result->IsMinusZero()) {
26 Handle<String> str = Object::ToString(isolate, result).ToHandleChecked();
28 if (!str->SameValue(*s))
return false;
35 inline int ConvertToMb(
size_t size) {
36 return static_cast<int>(size /
static_cast<size_t>(MB));
41 void JSArrayBuffer::Neuter() {
42 CHECK(is_neuterable());
43 CHECK(!was_neutered());
45 set_backing_store(
nullptr);
47 set_was_neutered(
true);
48 set_is_neuterable(
false);
50 Isolate*
const isolate = GetIsolate();
51 if (isolate->IsArrayBufferNeuteringIntact()) {
52 isolate->InvalidateArrayBufferNeuteringProtector();
56 void JSArrayBuffer::FreeBackingStoreFromMainThread() {
57 if (allocation_base() ==
nullptr) {
60 FreeBackingStore(GetIsolate(), {allocation_base(), allocation_length(),
61 backing_store(), is_wasm_memory()});
64 set_backing_store(
nullptr);
68 void JSArrayBuffer::FreeBackingStore(Isolate* isolate, Allocation allocation) {
69 if (allocation.is_wasm_memory) {
70 wasm::WasmMemoryTracker* memory_tracker =
71 isolate->wasm_engine()->memory_tracker();
72 if (!memory_tracker->FreeMemoryIfIsWasmMemory(isolate,
73 allocation.backing_store)) {
74 CHECK(FreePages(GetPlatformPageAllocator(), allocation.allocation_base,
78 isolate->array_buffer_allocator()->Free(allocation.allocation_base,
83 void JSArrayBuffer::Setup(Handle<JSArrayBuffer> array_buffer, Isolate* isolate,
84 bool is_external,
void* data,
size_t byte_length,
85 SharedFlag shared_flag,
bool is_wasm_memory) {
86 DCHECK_EQ(array_buffer->GetEmbedderFieldCount(),
87 v8::ArrayBuffer::kEmbedderFieldCount);
88 DCHECK_LE(byte_length, JSArrayBuffer::kMaxByteLength);
89 for (
int i = 0;
i < v8::ArrayBuffer::kEmbedderFieldCount;
i++) {
90 array_buffer->SetEmbedderField(
i, Smi::kZero);
92 array_buffer->set_byte_length(byte_length);
93 array_buffer->set_bit_field(0);
94 array_buffer->clear_padding();
95 array_buffer->set_is_external(is_external);
96 array_buffer->set_is_neuterable(shared_flag == SharedFlag::kNotShared);
97 array_buffer->set_is_shared(shared_flag == SharedFlag::kShared);
98 array_buffer->set_is_wasm_memory(is_wasm_memory);
103 array_buffer->set_backing_store(data);
105 if (data && !is_external) {
106 isolate->heap()->RegisterNewArrayBuffer(*array_buffer);
110 void JSArrayBuffer::SetupAsEmpty(Handle<JSArrayBuffer> array_buffer,
112 Setup(array_buffer, isolate,
false,
nullptr, 0, SharedFlag::kNotShared);
115 bool JSArrayBuffer::SetupAllocatingData(Handle<JSArrayBuffer> array_buffer,
117 size_t allocated_length,
119 SharedFlag shared_flag) {
121 CHECK_NOT_NULL(isolate->array_buffer_allocator());
122 if (allocated_length != 0) {
123 if (allocated_length >= MB)
124 isolate->counters()->array_buffer_big_allocations()->AddSample(
125 ConvertToMb(allocated_length));
126 if (shared_flag == SharedFlag::kShared)
127 isolate->counters()->shared_array_allocations()->AddSample(
128 ConvertToMb(allocated_length));
130 data = isolate->array_buffer_allocator()->Allocate(allocated_length);
132 data = isolate->array_buffer_allocator()->AllocateUninitialized(
135 if (data ==
nullptr) {
136 isolate->counters()->array_buffer_new_size_failures()->AddSample(
137 ConvertToMb(allocated_length));
138 SetupAsEmpty(array_buffer, isolate);
145 const bool is_external =
false;
146 JSArrayBuffer::Setup(array_buffer, isolate, is_external, data,
147 allocated_length, shared_flag);
151 Handle<JSArrayBuffer> JSTypedArray::MaterializeArrayBuffer(
152 Handle<JSTypedArray> typed_array) {
153 DCHECK(typed_array->is_on_heap());
155 Isolate* isolate = typed_array->GetIsolate();
157 DCHECK(IsFixedTypedArrayElementsKind(typed_array->GetElementsKind()));
159 Handle<FixedTypedArrayBase> fixed_typed_array(
160 FixedTypedArrayBase::cast(typed_array->elements()), isolate);
162 Handle<JSArrayBuffer> buffer(JSArrayBuffer::cast(typed_array->buffer()),
165 DCHECK(!buffer->is_wasm_memory());
167 void* backing_store =
168 isolate->array_buffer_allocator()->AllocateUninitialized(
169 fixed_typed_array->DataSize());
170 if (backing_store ==
nullptr) {
171 isolate->heap()->FatalProcessOutOfMemory(
172 "JSTypedArray::MaterializeArrayBuffer");
174 buffer->set_is_external(
false);
175 DCHECK_EQ(buffer->byte_length(),
176 static_cast<uintptr_t>(fixed_typed_array->DataSize()));
181 buffer->set_backing_store(backing_store);
183 isolate->heap()->RegisterNewArrayBuffer(*buffer);
184 memcpy(buffer->backing_store(), fixed_typed_array->DataPtr(),
185 fixed_typed_array->DataSize());
186 Handle<FixedTypedArrayBase> new_elements =
187 isolate->factory()->NewFixedTypedArrayWithExternalPointer(
188 fixed_typed_array->length(), typed_array->type(),
189 static_cast<uint8_t*
>(buffer->backing_store()));
191 typed_array->set_elements(*new_elements);
192 DCHECK(!typed_array->is_on_heap());
197 Handle<JSArrayBuffer> JSTypedArray::GetBuffer() {
199 Handle<JSArrayBuffer> array_buffer(JSArrayBuffer::cast(buffer()),
203 Handle<JSTypedArray>
self(
this, GetIsolate());
204 return MaterializeArrayBuffer(
self);
209 Maybe<bool> JSTypedArray::DefineOwnProperty(Isolate* isolate,
210 Handle<JSTypedArray> o,
212 PropertyDescriptor* desc,
213 ShouldThrow should_throw) {
215 DCHECK(key->IsName() || key->IsNumber());
218 if (key->IsString() || key->IsSmi()) {
221 Handle<Object> numeric_index;
222 if (CanonicalNumericIndexString(isolate, key, &numeric_index)) {
228 if (numeric_index->IsMinusZero() || !numeric_index->ToUint32(&index)) {
229 RETURN_FAILURE(isolate, should_throw,
230 NewTypeError(MessageTemplate::kInvalidTypedArrayIndex));
233 size_t length = o->length_value();
235 if (o->WasNeutered() || index >= length) {
236 RETURN_FAILURE(isolate, should_throw,
237 NewTypeError(MessageTemplate::kInvalidTypedArrayIndex));
240 if (PropertyDescriptor::IsAccessorDescriptor(desc)) {
241 RETURN_FAILURE(isolate, should_throw,
242 NewTypeError(MessageTemplate::kRedefineDisallowed, key));
250 if ((desc->has_configurable() && desc->configurable()) ||
251 (desc->has_enumerable() && !desc->enumerable()) ||
252 (desc->has_writable() && !desc->writable())) {
253 RETURN_FAILURE(isolate, should_throw,
254 NewTypeError(MessageTemplate::kRedefineDisallowed, key));
259 if (desc->has_value()) {
260 if (!desc->has_configurable()) desc->set_configurable(
false);
261 if (!desc->has_enumerable()) desc->set_enumerable(
true);
262 if (!desc->has_writable()) desc->set_writable(
true);
263 Handle<Object> value = desc->value();
264 RETURN_ON_EXCEPTION_VALUE(isolate,
265 SetOwnElementIgnoreAttributes(
266 o, index, value, desc->ToAttributes()),
274 return OrdinaryDefineOwnProperty(isolate, o, key, desc, should_throw);
277 ExternalArrayType JSTypedArray::type() {
278 switch (elements()->map()->instance_type()) {
279 #define INSTANCE_TYPE_TO_ARRAY_TYPE(Type, type, TYPE, ctype) \ 280 case FIXED_##TYPE##_ARRAY_TYPE: \ 281 return kExternal##Type##Array; 283 TYPED_ARRAYS(INSTANCE_TYPE_TO_ARRAY_TYPE)
284 #undef INSTANCE_TYPE_TO_ARRAY_TYPE 291 size_t JSTypedArray::element_size() {
292 switch (elements()->map()->instance_type()) {
293 #define INSTANCE_TYPE_TO_ELEMENT_SIZE(Type, type, TYPE, ctype) \ 294 case FIXED_##TYPE##_ARRAY_TYPE: \ 295 return sizeof(ctype); 297 TYPED_ARRAYS(INSTANCE_TYPE_TO_ELEMENT_SIZE)
298 #undef INSTANCE_TYPE_TO_ELEMENT_SIZE