mirror of
https://github.com/dart-lang/sdk
synced 2024-11-05 18:22:09 +00:00
e2be5322e6
Seemingly Windows doesn't always implement realloc() by freeing space if the new buffer is significantly smaller than the old one. This CL does so manually in our code base. Issue b/178993708 Issue https://github.com/dart-lang/sdk/issues/44846 TEST=standalone{,_2}/io/large_file_read_small_file_test Change-Id: I370346a693f8e8e879e079d91e9de5c756949a11 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/183694 Reviewed-by: Vyacheslav Egorov <vegorov@google.com> Commit-Queue: Martin Kustermann <kustermann@google.com>
61 lines
1.8 KiB
C++
61 lines
1.8 KiB
C++
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
|
|
#include "bin/io_buffer.h"
|
|
|
|
#include "platform/memory_sanitizer.h"
|
|
|
|
namespace dart {
|
|
namespace bin {
|
|
|
|
Dart_Handle IOBuffer::Allocate(intptr_t size, uint8_t** buffer) {
|
|
uint8_t* data = Allocate(size);
|
|
if (data == NULL) {
|
|
return Dart_Null();
|
|
}
|
|
Dart_Handle result = Dart_NewExternalTypedDataWithFinalizer(
|
|
Dart_TypedData_kUint8, data, size, data, size, IOBuffer::Finalizer);
|
|
|
|
if (Dart_IsError(result)) {
|
|
Free(data);
|
|
Dart_PropagateError(result);
|
|
}
|
|
if (buffer != NULL) {
|
|
*buffer = data;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
uint8_t* IOBuffer::Allocate(intptr_t size) {
|
|
return static_cast<uint8_t*>(calloc(size, sizeof(uint8_t)));
|
|
}
|
|
|
|
uint8_t* IOBuffer::Reallocate(uint8_t* buffer, intptr_t new_size) {
|
|
if (new_size == 0) {
|
|
// The call to `realloc()` below has a corner case if the new size is 0:
|
|
// It can return `nullptr` in that case even though `malloc(0)` would
|
|
// return a unique non-`nullptr` value. To avoid returning `nullptr` on
|
|
// successful realloc, we handle this case specially.
|
|
auto new_buffer = IOBuffer::Allocate(0);
|
|
if (new_buffer != nullptr) {
|
|
free(buffer);
|
|
return new_buffer;
|
|
}
|
|
return buffer;
|
|
}
|
|
#if defined(TARGET_OS_WINDOWS)
|
|
// It seems windows realloc() doesn't free memory when shrinking, so we'll
|
|
// manually allocate a new buffer, copy the data and free the old buffer.
|
|
auto new_buffer = IOBuffer::Allocate(new_size);
|
|
if (new_buffer != nullptr) {
|
|
memmove(new_buffer, buffer, new_size);
|
|
free(buffer);
|
|
return static_cast<uint8_t*>(new_buffer);
|
|
}
|
|
#endif
|
|
return static_cast<uint8_t*>(realloc(buffer, new_size));
|
|
}
|
|
|
|
} // namespace bin
|
|
} // namespace dart
|