mirror of
https://github.com/dart-lang/sdk
synced 2024-09-15 23:39:48 +00:00
[vm] Produce clearer error messages when operator new fails.
TEST=bots Bug: https://github.com/dart-lang/sdk/issues/43642 Bug: https://github.com/dart-lang/sdk/issues/43862 Change-Id: I598a26a56762c141a1aef972f7d32f2c9594b244 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/171802 Commit-Queue: Ryan Macnak <rmacnak@google.com> Reviewed-by: Alexander Aprelev <aam@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com>
This commit is contained in:
parent
82637793bf
commit
1d05591fbb
|
@ -5,6 +5,7 @@
|
||||||
#ifndef RUNTIME_PLATFORM_ALLOCATION_H_
|
#ifndef RUNTIME_PLATFORM_ALLOCATION_H_
|
||||||
#define RUNTIME_PLATFORM_ALLOCATION_H_
|
#define RUNTIME_PLATFORM_ALLOCATION_H_
|
||||||
|
|
||||||
|
#include "platform/address_sanitizer.h"
|
||||||
#include "platform/assert.h"
|
#include "platform/assert.h"
|
||||||
|
|
||||||
namespace dart {
|
namespace dart {
|
||||||
|
@ -31,6 +32,36 @@ class AllStatic {
|
||||||
DISALLOW_IMPLICIT_CONSTRUCTORS(AllStatic);
|
DISALLOW_IMPLICIT_CONSTRUCTORS(AllStatic);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class MallocAllocated {
|
||||||
|
public:
|
||||||
|
MallocAllocated() {}
|
||||||
|
|
||||||
|
// Intercept operator new to produce clearer error messages when we run out
|
||||||
|
// of memory. Don't do this when running under ASAN so it can continue to
|
||||||
|
// check malloc/new/new[] are paired with free/delete/delete[] respectively.
|
||||||
|
#if !defined(USING_ADDRESS_SANITIZER)
|
||||||
|
void* operator new(size_t size) {
|
||||||
|
void* result = ::malloc(size);
|
||||||
|
if (result == nullptr) {
|
||||||
|
OUT_OF_MEMORY();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* operator new[](size_t size) {
|
||||||
|
void* result = ::malloc(size);
|
||||||
|
if (result == nullptr) {
|
||||||
|
OUT_OF_MEMORY();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator delete(void* pointer) { ::free(pointer); }
|
||||||
|
|
||||||
|
void operator delete[](void* pointer) { ::free(pointer); }
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace dart
|
} // namespace dart
|
||||||
|
|
||||||
#endif // RUNTIME_PLATFORM_ALLOCATION_H_
|
#endif // RUNTIME_PLATFORM_ALLOCATION_H_
|
||||||
|
|
|
@ -254,14 +254,13 @@ class Malloc : public AllStatic {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class EmptyBase {};
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class MallocGrowableArray : public BaseGrowableArray<T, EmptyBase, Malloc> {
|
class MallocGrowableArray
|
||||||
|
: public BaseGrowableArray<T, MallocAllocated, Malloc> {
|
||||||
public:
|
public:
|
||||||
explicit MallocGrowableArray(intptr_t initial_capacity)
|
explicit MallocGrowableArray(intptr_t initial_capacity)
|
||||||
: BaseGrowableArray<T, EmptyBase, Malloc>(initial_capacity, NULL) {}
|
: BaseGrowableArray<T, MallocAllocated, Malloc>(initial_capacity, NULL) {}
|
||||||
MallocGrowableArray() : BaseGrowableArray<T, EmptyBase, Malloc>(NULL) {}
|
MallocGrowableArray() : BaseGrowableArray<T, MallocAllocated, Malloc>(NULL) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace dart
|
} // namespace dart
|
||||||
|
|
|
@ -157,9 +157,6 @@ SimpleHashMap::Entry* SimpleHashMap::Probe(void* key, uint32_t hash) {
|
||||||
void SimpleHashMap::Initialize(uint32_t capacity) {
|
void SimpleHashMap::Initialize(uint32_t capacity) {
|
||||||
ASSERT(dart::Utils::IsPowerOfTwo(capacity));
|
ASSERT(dart::Utils::IsPowerOfTwo(capacity));
|
||||||
map_ = new Entry[capacity];
|
map_ = new Entry[capacity];
|
||||||
if (map_ == NULL) {
|
|
||||||
OUT_OF_MEMORY();
|
|
||||||
}
|
|
||||||
capacity_ = capacity;
|
capacity_ = capacity;
|
||||||
occupancy_ = 0;
|
occupancy_ = 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,10 +54,10 @@ class ZoneAllocated {
|
||||||
ZoneAllocated() {}
|
ZoneAllocated() {}
|
||||||
|
|
||||||
// Implicitly allocate the object in the current zone.
|
// Implicitly allocate the object in the current zone.
|
||||||
void* operator new(uword size);
|
void* operator new(size_t size);
|
||||||
|
|
||||||
// Allocate the object in the given zone, which must be the current zone.
|
// Allocate the object in the given zone, which must be the current zone.
|
||||||
void* operator new(uword size, Zone* zone);
|
void* operator new(size_t size, Zone* zone);
|
||||||
|
|
||||||
// Ideally, the delete operator should be protected instead of
|
// Ideally, the delete operator should be protected instead of
|
||||||
// public, but unfortunately the compiler sometimes synthesizes
|
// public, but unfortunately the compiler sometimes synthesizes
|
||||||
|
|
|
@ -27,7 +27,7 @@ class TimelineEvent;
|
||||||
|
|
||||||
// Holds all data relevant for execution of deoptimization instructions.
|
// Holds all data relevant for execution of deoptimization instructions.
|
||||||
// Structure is allocated in C-heap.
|
// Structure is allocated in C-heap.
|
||||||
class DeoptContext {
|
class DeoptContext : public MallocAllocated {
|
||||||
public:
|
public:
|
||||||
enum DestFrameOptions {
|
enum DestFrameOptions {
|
||||||
kDestIsOriginalFrame, // Replace the original frame with deopt frame.
|
kDestIsOriginalFrame, // Replace the original frame with deopt frame.
|
||||||
|
|
|
@ -116,7 +116,7 @@ class Handles {
|
||||||
// is allocated from the chunk until we run out space in the chunk,
|
// is allocated from the chunk until we run out space in the chunk,
|
||||||
// at this point another chunk is allocated. These chunks are chained
|
// at this point another chunk is allocated. These chunks are chained
|
||||||
// together.
|
// together.
|
||||||
class HandlesBlock {
|
class HandlesBlock : public MallocAllocated {
|
||||||
public:
|
public:
|
||||||
explicit HandlesBlock(HandlesBlock* next)
|
explicit HandlesBlock(HandlesBlock* next)
|
||||||
: next_handle_slot_(0), next_block_(next) {}
|
: next_handle_slot_(0), next_block_(next) {}
|
||||||
|
|
|
@ -157,9 +157,6 @@ void Handles<kHandleSizeInWords, kHandlesPerChunk, kOffsetOfRawPtr>::
|
||||||
}
|
}
|
||||||
if (scoped_blocks_->next_block() == NULL) {
|
if (scoped_blocks_->next_block() == NULL) {
|
||||||
HandlesBlock* block = new HandlesBlock(NULL);
|
HandlesBlock* block = new HandlesBlock(NULL);
|
||||||
if (block == NULL) {
|
|
||||||
OUT_OF_MEMORY();
|
|
||||||
}
|
|
||||||
scoped_blocks_->set_next_block(block);
|
scoped_blocks_->set_next_block(block);
|
||||||
}
|
}
|
||||||
scoped_blocks_ = scoped_blocks_->next_block();
|
scoped_blocks_ = scoped_blocks_->next_block();
|
||||||
|
@ -207,9 +204,6 @@ void Handles<kHandleSizeInWords, kHandlesPerChunk, kOffsetOfRawPtr>::
|
||||||
CountScopedHandles());
|
CountScopedHandles());
|
||||||
}
|
}
|
||||||
zone_blocks_ = new HandlesBlock(zone_blocks_);
|
zone_blocks_ = new HandlesBlock(zone_blocks_);
|
||||||
if (zone_blocks_ == NULL) {
|
|
||||||
OUT_OF_MEMORY();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(DEBUG)
|
#if defined(DEBUG)
|
||||||
|
|
|
@ -423,15 +423,17 @@ class DirectChainedHashMap
|
||||||
|
|
||||||
template <typename KeyValueTrait>
|
template <typename KeyValueTrait>
|
||||||
class MallocDirectChainedHashMap
|
class MallocDirectChainedHashMap
|
||||||
: public BaseDirectChainedHashMap<KeyValueTrait, EmptyBase, Malloc> {
|
: public BaseDirectChainedHashMap<KeyValueTrait, MallocAllocated, Malloc> {
|
||||||
public:
|
public:
|
||||||
MallocDirectChainedHashMap()
|
MallocDirectChainedHashMap()
|
||||||
: BaseDirectChainedHashMap<KeyValueTrait, EmptyBase, Malloc>(NULL) {}
|
: BaseDirectChainedHashMap<KeyValueTrait, MallocAllocated, Malloc>(NULL) {
|
||||||
|
}
|
||||||
|
|
||||||
// The only use of the copy constructor seems to be in hash_map_test.cc.
|
// The only use of the copy constructor seems to be in hash_map_test.cc.
|
||||||
// Not disallowing it for now just in case there are other users.
|
// Not disallowing it for now just in case there are other users.
|
||||||
MallocDirectChainedHashMap(const MallocDirectChainedHashMap& other)
|
MallocDirectChainedHashMap(const MallocDirectChainedHashMap& other)
|
||||||
: BaseDirectChainedHashMap<KeyValueTrait, EmptyBase, Malloc>(other) {}
|
: BaseDirectChainedHashMap<KeyValueTrait, MallocAllocated, Malloc>(
|
||||||
|
other) {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void operator=(const MallocDirectChainedHashMap& other) = delete;
|
void operator=(const MallocDirectChainedHashMap& other) = delete;
|
||||||
|
|
|
@ -18,7 +18,7 @@ class ObjectPointerVisitor;
|
||||||
|
|
||||||
// A set of ObjectPtr. Must be emptied before destruction (using Pop/Reset).
|
// A set of ObjectPtr. Must be emptied before destruction (using Pop/Reset).
|
||||||
template <int Size>
|
template <int Size>
|
||||||
class PointerBlock {
|
class PointerBlock : public MallocAllocated {
|
||||||
public:
|
public:
|
||||||
enum { kSize = Size };
|
enum { kSize = Size };
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
#include "include/dart_api.h"
|
#include "include/dart_api.h"
|
||||||
|
|
||||||
|
#include "platform/allocation.h"
|
||||||
#include "platform/globals.h"
|
#include "platform/globals.h"
|
||||||
#include "platform/utils.h"
|
#include "platform/utils.h"
|
||||||
|
|
||||||
|
@ -18,7 +19,7 @@ class PortSet {
|
||||||
static constexpr Dart_Port kFreePort = static_cast<Dart_Port>(0);
|
static constexpr Dart_Port kFreePort = static_cast<Dart_Port>(0);
|
||||||
static constexpr Dart_Port kDeletedPort = static_cast<Dart_Port>(3);
|
static constexpr Dart_Port kDeletedPort = static_cast<Dart_Port>(3);
|
||||||
|
|
||||||
struct Entry {
|
struct Entry : public MallocAllocated {
|
||||||
Entry() : port(kFreePort) {}
|
Entry() : port(kFreePort) {}
|
||||||
|
|
||||||
// Free entries have set this to 0.
|
// Free entries have set this to 0.
|
||||||
|
|
|
@ -574,7 +574,7 @@ class TimelineBeginEndScope : public TimelineEventScope {
|
||||||
};
|
};
|
||||||
|
|
||||||
// A block of |TimelineEvent|s. Not thread safe.
|
// A block of |TimelineEvent|s. Not thread safe.
|
||||||
class TimelineEventBlock {
|
class TimelineEventBlock : public MallocAllocated {
|
||||||
public:
|
public:
|
||||||
static const intptr_t kBlockSize = 64;
|
static const intptr_t kBlockSize = 64;
|
||||||
|
|
||||||
|
@ -707,7 +707,7 @@ class IsolateTimelineEventFilter : public TimelineEventFilter {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Recorder of |TimelineEvent|s.
|
// Recorder of |TimelineEvent|s.
|
||||||
class TimelineEventRecorder {
|
class TimelineEventRecorder : public MallocAllocated {
|
||||||
public:
|
public:
|
||||||
TimelineEventRecorder();
|
TimelineEventRecorder();
|
||||||
virtual ~TimelineEventRecorder() {}
|
virtual ~TimelineEventRecorder() {}
|
||||||
|
|
Loading…
Reference in a new issue