dart-sdk/runtime/bin/io_buffer.cc
Martin Kustermann e2be5322e6 [vm] Use custom realloc() on Windows
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>
2021-03-02 16:02:52 +00:00

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