Revert "[vm] Streamline Zones."

This reverts commit b5922e6db4.

Reason for revert: vm/cc/AllocateZone fails on Mac

Original change's description:
> [vm] Streamline Zones.
>
>  - Don't put a HANDLESCOPE right after a StackZone, as there's no state worth restoring
>  - Remove remaining zone bookkeeping dead since e3a9d70591.
>  - Remove unnecessary resetting of handle blocks before zone deletion.
>  - Shrink initial chunk size to make Zone's overall size fit in a faster malloc size class.
>
> TEST=ci
> Change-Id: I920e12f5af93aa71fb876435764c60df485215f9
> Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/212261
> Reviewed-by: Siva Annamalai <asiva@google.com>
> Commit-Queue: Ryan Macnak <rmacnak@google.com>

TBR=rmacnak@google.com,asiva@google.com

Change-Id: Id23dcebb781791616e48e54d2dcd7e58159178bc
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/215943
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Ryan Macnak <rmacnak@google.com>
This commit is contained in:
Ryan Macnak
2021-10-06 23:44:33 +00:00
committed by commit-bot@chromium.org
parent bfbf75a1f6
commit 472e2bce17
28 changed files with 2408 additions and 2230 deletions
+8
View File
@@ -48,6 +48,7 @@ BENCHMARK(CorelibCompileAll) {
bin::Builtin::SetNativeResolver(bin::Builtin::kCLILibrary);
TransitionNativeToVM transition(thread);
StackZone zone(thread);
HANDLESCOPE(thread);
Timer timer;
timer.Start();
const Error& error =
@@ -412,6 +413,7 @@ BENCHMARK_SIZE(CoreSnapshotSize) {
TransitionNativeToVM transition(thread);
StackZone zone(thread);
HANDLESCOPE(thread);
Api::CheckAndFinalizePendingClasses(thread);
@@ -449,6 +451,7 @@ BENCHMARK_SIZE(StandaloneSnapshotSize) {
TransitionNativeToVM transition(thread);
StackZone zone(thread);
HANDLESCOPE(thread);
Api::CheckAndFinalizePendingClasses(thread);
@@ -493,6 +496,7 @@ BENCHMARK(EnterExitIsolate) {
{
TransitionNativeToVM transition(thread);
StackZone zone(thread);
HANDLESCOPE(thread);
Api::CheckAndFinalizePendingClasses(thread);
}
Dart_Isolate isolate = Dart_CurrentIsolate();
@@ -510,6 +514,7 @@ BENCHMARK(EnterExitIsolate) {
BENCHMARK(SerializeNull) {
TransitionNativeToVM transition(thread);
StackZone zone(thread);
HANDLESCOPE(thread);
const Object& null_object = Object::Handle();
const intptr_t kLoopCount = 1000000;
Timer timer;
@@ -531,6 +536,7 @@ BENCHMARK(SerializeNull) {
BENCHMARK(SerializeSmi) {
TransitionNativeToVM transition(thread);
StackZone zone(thread);
HANDLESCOPE(thread);
const Integer& smi_object = Integer::Handle(Smi::New(42));
const intptr_t kLoopCount = 1000000;
Timer timer;
@@ -552,6 +558,7 @@ BENCHMARK(SerializeSmi) {
BENCHMARK(SimpleMessage) {
TransitionNativeToVM transition(thread);
StackZone zone(thread);
HANDLESCOPE(thread);
const Array& array_object = Array::Handle(Array::New(2));
array_object.SetAt(0, Integer::Handle(Smi::New(42)));
array_object.SetAt(1, Object::Handle());
@@ -585,6 +592,7 @@ BENCHMARK(LargeMap) {
EXPECT_VALID(h_result);
TransitionNativeToVM transition(thread);
StackZone zone(thread);
HANDLESCOPE(thread);
Instance& map = Instance::Handle();
map ^= Api::UnwrapHandle(h_result);
const intptr_t kLoopCount = 100;
+1
View File
@@ -1731,6 +1731,7 @@ void ClassFinalizer::ClearAllCode(bool including_nonchanging_cids) {
auto const isolate_group = thread->isolate_group();
SafepointWriteRwLocker ml(thread, isolate_group->program_lock());
StackZone stack_zone(thread);
HANDLESCOPE(thread);
auto const zone = thread->zone();
class ClearCodeVisitor : public FunctionVisitor {
+1
View File
@@ -3009,6 +3009,7 @@ void Precompiler::FinalizeAllClasses() {
// otherwise unreachable constants of dropped classes, which would
// cause assertion failures during GC after classes are dropped.
StackZone stack_zone(thread());
HANDLESCOPE(thread());
error_ = Library::FinalizeAllClasses();
if (!error_.IsNull()) {
+1
View File
@@ -1133,6 +1133,7 @@ void BackgroundCompiler::Run() {
Thread* thread = Thread::Current();
StackZone stack_zone(thread);
Zone* zone = stack_zone.GetZone();
HANDLESCOPE(thread);
Function& function = Function::Handle(zone);
{
SafepointMonitorLocker ml(&queue_monitor_);
File diff suppressed because it is too large Load Diff
+2
View File
@@ -1301,6 +1301,7 @@ static Dart_Isolate CreateIsolate(IsolateGroup* group,
bool success = false;
{
StackZone zone(T);
HANDLESCOPE(T);
// We enter an API scope here as InitializeIsolate could compile some
// bootstrap library files which call out to a tag handler that may create
// Api Handles when an error is encountered.
@@ -2052,6 +2053,7 @@ DART_EXPORT bool Dart_RunLoopAsync(bool errors_are_fatal,
auto thread = Thread::Current();
TransitionNativeToVM transition(thread);
StackZone zone(thread);
HANDLESCOPE(thread);
if (on_error_port != ILLEGAL_PORT) {
const auto& port =
+2
View File
@@ -3128,6 +3128,7 @@ VM_UNIT_TEST_CASE(DartAPI_PersistentHandles) {
{
TransitionNativeToVM transition(thread);
StackZone zone(thread);
HANDLESCOPE(thread);
for (int i = 0; i < 500; i++) {
String& str = String::Handle();
str ^= PersistentHandle::Cast(handles[i])->ptr();
@@ -4550,6 +4551,7 @@ VM_UNIT_TEST_CASE(DartAPI_LocalHandles) {
{
TransitionNativeToVM transition1(thread);
StackZone zone(thread);
HANDLESCOPE(thread);
Smi& val = Smi::Handle();
TransitionVMToNative transition2(thread);
+2
View File
@@ -14,4 +14,6 @@
namespace dart {
RelaxedAtomic<intptr_t> ApiNativeScope::current_memory_usage_ = 0;
} // namespace dart
+21 -1
View File
@@ -110,7 +110,7 @@ class ApiZone {
if ((thread != NULL) && (thread->zone() == &zone_)) {
thread->set_zone(zone_.previous_);
}
zone_.Reset();
zone_.DeleteAll();
}
private:
@@ -656,11 +656,18 @@ class ApiNativeScope {
ASSERT(Current() == NULL);
OSThread::SetThreadLocal(Api::api_native_key_,
reinterpret_cast<uword>(this));
// We manually increment the memory usage counter since there is memory
// initially allocated within the zone on creation.
IncrementNativeScopeMemoryCapacity(zone_.GetZone()->CapacityInBytes());
}
~ApiNativeScope() {
ASSERT(Current() == this);
OSThread::SetThreadLocal(Api::api_native_key_, 0);
// We must also manually decrement the memory usage counter since the native
// is still holding it's initial memory and ~Zone() won't be able to
// determine which memory usage counter to decrement.
DecrementNativeScopeMemoryCapacity(zone_.GetZone()->CapacityInBytes());
}
static inline ApiNativeScope* Current() {
@@ -668,6 +675,16 @@ class ApiNativeScope {
OSThread::GetThreadLocal(Api::api_native_key_));
}
static uintptr_t current_memory_usage() { return current_memory_usage_; }
static void IncrementNativeScopeMemoryCapacity(intptr_t size) {
current_memory_usage_.fetch_add(size);
}
static void DecrementNativeScopeMemoryCapacity(intptr_t size) {
current_memory_usage_.fetch_sub(size);
}
Zone* zone() {
Zone* result = zone_.GetZone();
ASSERT(result->handles()->CountScopedHandles() == 0);
@@ -676,6 +693,9 @@ class ApiNativeScope {
}
private:
// The current total memory usage within ApiNativeScopes.
static RelaxedAtomic<intptr_t> current_memory_usage_;
ApiZone zone_;
};
+10
View File
@@ -19,6 +19,16 @@ namespace dart {
DEFINE_FLAG(bool, verify_handles, false, "Verify handles.");
VMHandles::~VMHandles() {
if (FLAG_trace_handles) {
OS::PrintErr("*** Handle Counts for 0x(%" Px "):Zone = %d,Scoped = %d\n",
reinterpret_cast<intptr_t>(this), CountZoneHandles(),
CountScopedHandles());
OS::PrintErr("*** Deleting VM handle block 0x%" Px "\n",
reinterpret_cast<intptr_t>(this));
}
}
void VMHandles::VisitObjectPointers(ObjectPointerVisitor* visitor) {
return Handles<kVMHandleSizeInWords, kVMHandlesPerChunk,
kOffsetOfRawPtr>::VisitObjectPointers(visitor);
+5 -36
View File
@@ -107,24 +107,6 @@ class Handles {
return true;
}
intptr_t ZoneHandlesCapacityInBytes() const {
intptr_t capacity = 0;
for (HandlesBlock* block = zone_blocks_; block != nullptr;
block = block->next_block()) {
capacity += sizeof(*block);
}
return capacity;
}
intptr_t ScopedHandlesCapacityInBytes() const {
intptr_t capacity = 0;
for (HandlesBlock* block = scoped_blocks_; block != nullptr;
block = block->next_block()) {
capacity += sizeof(*block);
}
return capacity;
}
protected:
// Returns a count of active handles (used for testing purposes).
int CountScopedHandles() const;
@@ -144,7 +126,7 @@ class Handles {
class HandlesBlock : public MallocAllocated {
public:
explicit HandlesBlock(HandlesBlock* next)
: next_block_(next), next_handle_slot_(0) {}
: next_handle_slot_(0), next_block_(next) {}
~HandlesBlock();
// Reinitializes handle block for reuse.
@@ -193,9 +175,9 @@ class Handles {
void set_next_block(HandlesBlock* next) { next_block_ = next; }
private:
HandlesBlock* next_block_; // Link to next block of handles.
intptr_t next_handle_slot_; // Next slot for allocation in current block.
uword data_[kHandleSizeInWords * kHandlesPerChunk]; // Handles area.
intptr_t next_handle_slot_; // Next slot for allocation in current block.
HandlesBlock* next_block_; // Link to next block of handles.
DISALLOW_COPY_AND_ASSIGN(HandlesBlock);
};
@@ -240,7 +222,7 @@ class Handles {
};
static const int kVMHandleSizeInWords = 2;
static const int kVMHandlesPerChunk = 63;
static const int kVMHandlesPerChunk = 64;
static const int kOffsetOfRawPtr = kWordSize;
class VMHandles : public Handles<kVMHandleSizeInWords,
kVMHandlesPerChunk,
@@ -250,25 +232,12 @@ class VMHandles : public Handles<kVMHandleSizeInWords,
VMHandles()
: Handles<kVMHandleSizeInWords, kVMHandlesPerChunk, kOffsetOfRawPtr>() {
#if defined(DEBUG)
if (FLAG_trace_handles) {
OS::PrintErr("*** Starting a new VM handle block 0x%" Px "\n",
reinterpret_cast<intptr_t>(this));
}
#endif
}
~VMHandles() {
#if defined(DEBUG)
if (FLAG_trace_handles) {
OS::PrintErr("*** Handle Counts for 0x(%" Px
"):Zone = %d,Scoped = %d\n",
reinterpret_cast<intptr_t>(this), CountZoneHandles(),
CountScopedHandles());
OS::PrintErr("*** Deleting VM handle block 0x%" Px "\n",
reinterpret_cast<intptr_t>(this));
}
#endif
}
~VMHandles();
// Visit all object pointers stored in the various handles.
void VisitObjectPointers(ObjectPointerVisitor* visitor);
+1
View File
@@ -81,6 +81,7 @@ uword Handles<kHandleSizeInWords, kHandlesPerChunk, kOffsetOfRawPtr>::
AllocateHandle(Zone* zone) {
#if defined(DEBUG)
Thread* thread = Thread::Current();
ASSERT(thread->top_handle_scope() != NULL);
ASSERT(thread->MayAllocateHandles());
#endif // DEBUG
Handles* handles = zone->handles();
+3
View File
@@ -592,6 +592,7 @@ VM_UNIT_TEST_CASE(CleanupBequestNeverReceived) {
Thread* thread = Thread::Current();
TransitionNativeToVM transition(thread);
StackZone zone(thread);
HANDLESCOPE(thread);
String& string = String::Handle(String::New(TEST_MESSAGE));
PersistentHandle* handle =
@@ -625,6 +626,7 @@ VM_UNIT_TEST_CASE(ReceivesSendAndExitMessage) {
Thread* thread = Thread::Current();
TransitionNativeToVM transition(thread);
StackZone zone(thread);
HANDLESCOPE(thread);
String& string = String::Handle(String::New(TEST_MESSAGE));
@@ -642,6 +644,7 @@ VM_UNIT_TEST_CASE(ReceivesSendAndExitMessage) {
Thread* thread = Thread::Current();
TransitionNativeToVM transition(thread);
StackZone zone(thread);
HANDLESCOPE(thread);
EXPECT_EQ(MessageHandler::kOK, handler.HandleNextMessage());
}
+1
View File
@@ -174,6 +174,7 @@ class RunKernelTask : public ThreadPool::Task {
Thread* T = Thread::Current();
ASSERT(I == T->isolate());
StackZone zone(T);
HANDLESCOPE(T);
// Invoke main which will return the port to which load requests are sent.
const Library& root_library =
Library::Handle(Z, I->group()->object_store()->root_library());
+1
View File
@@ -53,6 +53,7 @@ VM_UNIT_TEST_CASE(Metric_OnDemand) {
Thread* thread = Thread::Current();
TransitionNativeToVM transition(thread);
StackZone zone(thread);
HANDLESCOPE(thread);
MyMetric metric;
metric.InitInstance(Isolate::Current(), "a.b.c", "foobar", Metric::kByte);
+1
View File
@@ -1777,6 +1777,7 @@ void ProfilerService::PrintJSONImpl(Thread* thread,
ASSERT(buffer != nullptr);
StackZone zone(thread);
HANDLESCOPE(thread);
Profile profile;
profile.Build(thread, filter, buffer);
profile.PrintProfileJSON(stream, include_code_samples);
+47
View File
@@ -501,6 +501,7 @@ ISOLATE_UNIT_TEST_CASE(Profiler_TrivialRecordAllocation) {
Thread* thread = Thread::Current();
Isolate* isolate = thread->isolate();
StackZone zone(thread);
HANDLESCOPE(thread);
Profile profile;
// Filter for the class in the time range.
AllocationFilter filter(isolate->main_port(), class_a.id(),
@@ -530,6 +531,7 @@ ISOLATE_UNIT_TEST_CASE(Profiler_TrivialRecordAllocation) {
Thread* thread = Thread::Current();
Isolate* isolate = thread->isolate();
StackZone zone(thread);
HANDLESCOPE(thread);
Profile profile;
AllocationFilter filter(isolate->main_port(), class_a.id(),
Dart_TimelineGetMicros(), 16000);
@@ -576,6 +578,7 @@ ISOLATE_UNIT_TEST_CASE(Profiler_NativeAllocation) {
{
Thread* thread = Thread::Current();
StackZone zone(thread);
HANDLESCOPE(thread);
Profile profile;
// Filter for the class in the time range.
@@ -614,6 +617,7 @@ ISOLATE_UNIT_TEST_CASE(Profiler_NativeAllocation) {
{
Thread* thread = Thread::Current();
StackZone zone(thread);
HANDLESCOPE(thread);
Profile profile;
// Filter for the class in the time range.
@@ -628,6 +632,7 @@ ISOLATE_UNIT_TEST_CASE(Profiler_NativeAllocation) {
{
Thread* thread = Thread::Current();
StackZone zone(thread);
HANDLESCOPE(thread);
Profile profile;
NativeAllocationSampleFilter filter(Dart_TimelineGetMicros(), 16000);
profile.Build(thread, &filter, Profiler::sample_block_buffer());
@@ -673,6 +678,7 @@ ISOLATE_UNIT_TEST_CASE(Profiler_ToggleRecordAllocation) {
Thread* thread = Thread::Current();
Isolate* isolate = thread->isolate();
StackZone zone(thread);
HANDLESCOPE(thread);
Profile profile;
AllocationFilter filter(isolate->main_port(), class_a.id());
profile.Build(thread, &filter, Profiler::sample_block_buffer());
@@ -689,6 +695,7 @@ ISOLATE_UNIT_TEST_CASE(Profiler_ToggleRecordAllocation) {
Thread* thread = Thread::Current();
Isolate* isolate = thread->isolate();
StackZone zone(thread);
HANDLESCOPE(thread);
Profile profile;
AllocationFilter filter(isolate->main_port(), class_a.id());
profile.Build(thread, &filter, Profiler::sample_block_buffer());
@@ -718,6 +725,7 @@ ISOLATE_UNIT_TEST_CASE(Profiler_ToggleRecordAllocation) {
Thread* thread = Thread::Current();
Isolate* isolate = thread->isolate();
StackZone zone(thread);
HANDLESCOPE(thread);
Profile profile;
AllocationFilter filter(isolate->main_port(), class_a.id());
profile.Build(thread, &filter, Profiler::sample_block_buffer());
@@ -755,6 +763,7 @@ ISOLATE_UNIT_TEST_CASE(Profiler_CodeTicks) {
Thread* thread = Thread::Current();
Isolate* isolate = thread->isolate();
StackZone zone(thread);
HANDLESCOPE(thread);
Profile profile;
AllocationFilter filter(isolate->main_port(), class_a.id());
profile.Build(thread, &filter, Profiler::sample_block_buffer());
@@ -774,6 +783,7 @@ ISOLATE_UNIT_TEST_CASE(Profiler_CodeTicks) {
Thread* thread = Thread::Current();
Isolate* isolate = thread->isolate();
StackZone zone(thread);
HANDLESCOPE(thread);
Profile profile;
AllocationFilter filter(isolate->main_port(), class_a.id());
profile.Build(thread, &filter, Profiler::sample_block_buffer());
@@ -828,6 +838,7 @@ ISOLATE_UNIT_TEST_CASE(Profiler_FunctionTicks) {
Thread* thread = Thread::Current();
Isolate* isolate = thread->isolate();
StackZone zone(thread);
HANDLESCOPE(thread);
Profile profile;
AllocationFilter filter(isolate->main_port(), class_a.id());
profile.Build(thread, &filter, Profiler::sample_block_buffer());
@@ -847,6 +858,7 @@ ISOLATE_UNIT_TEST_CASE(Profiler_FunctionTicks) {
Thread* thread = Thread::Current();
Isolate* isolate = thread->isolate();
StackZone zone(thread);
HANDLESCOPE(thread);
Profile profile;
AllocationFilter filter(isolate->main_port(), class_a.id());
profile.Build(thread, &filter, Profiler::sample_block_buffer());
@@ -896,6 +908,7 @@ ISOLATE_UNIT_TEST_CASE(Profiler_IntrinsicAllocation) {
{
StackZone zone(thread);
HANDLESCOPE(thread);
Profile profile;
AllocationFilter filter(isolate->main_port(), double_class.id());
profile.Build(thread, &filter, Profiler::sample_block_buffer());
@@ -908,6 +921,7 @@ ISOLATE_UNIT_TEST_CASE(Profiler_IntrinsicAllocation) {
{
StackZone zone(thread);
HANDLESCOPE(thread);
Profile profile;
AllocationFilter filter(isolate->main_port(), double_class.id());
profile.Build(thread, &filter, Profiler::sample_block_buffer());
@@ -929,6 +943,7 @@ ISOLATE_UNIT_TEST_CASE(Profiler_IntrinsicAllocation) {
{
StackZone zone(thread);
HANDLESCOPE(thread);
Profile profile;
AllocationFilter filter(isolate->main_port(), double_class.id());
profile.Build(thread, &filter, Profiler::sample_block_buffer());
@@ -955,6 +970,7 @@ ISOLATE_UNIT_TEST_CASE(Profiler_ArrayAllocation) {
{
StackZone zone(thread);
HANDLESCOPE(thread);
Profile profile;
AllocationFilter filter(isolate->main_port(), array_class.id());
profile.Build(thread, &filter, Profiler::sample_block_buffer());
@@ -967,6 +983,7 @@ ISOLATE_UNIT_TEST_CASE(Profiler_ArrayAllocation) {
{
StackZone zone(thread);
HANDLESCOPE(thread);
Profile profile;
AllocationFilter filter(isolate->main_port(), array_class.id());
profile.Build(thread, &filter, Profiler::sample_block_buffer());
@@ -988,6 +1005,7 @@ ISOLATE_UNIT_TEST_CASE(Profiler_ArrayAllocation) {
{
StackZone zone(thread);
HANDLESCOPE(thread);
Profile profile;
AllocationFilter filter(isolate->main_port(), array_class.id());
profile.Build(thread, &filter, Profiler::sample_block_buffer());
@@ -1009,6 +1027,7 @@ ISOLATE_UNIT_TEST_CASE(Profiler_ArrayAllocation) {
{
StackZone zone(thread);
HANDLESCOPE(thread);
Profile profile;
AllocationFilter filter(isolate->main_port(), array_class.id());
profile.Build(thread, &filter, Profiler::sample_block_buffer());
@@ -1038,6 +1057,7 @@ ISOLATE_UNIT_TEST_CASE(Profiler_ContextAllocation) {
{
StackZone zone(thread);
HANDLESCOPE(thread);
Profile profile;
AllocationFilter filter(isolate->main_port(), context_class.id());
profile.Build(thread, &filter, Profiler::sample_block_buffer());
@@ -1050,6 +1070,7 @@ ISOLATE_UNIT_TEST_CASE(Profiler_ContextAllocation) {
{
StackZone zone(thread);
HANDLESCOPE(thread);
Profile profile;
AllocationFilter filter(isolate->main_port(), context_class.id());
profile.Build(thread, &filter, Profiler::sample_block_buffer());
@@ -1069,6 +1090,7 @@ ISOLATE_UNIT_TEST_CASE(Profiler_ContextAllocation) {
{
StackZone zone(thread);
HANDLESCOPE(thread);
Profile profile;
AllocationFilter filter(isolate->main_port(), context_class.id());
profile.Build(thread, &filter, Profiler::sample_block_buffer());
@@ -1108,6 +1130,7 @@ ISOLATE_UNIT_TEST_CASE(Profiler_ClosureAllocation) {
{
StackZone zone(thread);
HANDLESCOPE(thread);
Profile profile;
AllocationFilter filter(isolate->main_port(), closure_class.id());
filter.set_enable_vm_ticks(true);
@@ -1131,6 +1154,7 @@ ISOLATE_UNIT_TEST_CASE(Profiler_ClosureAllocation) {
{
StackZone zone(thread);
HANDLESCOPE(thread);
Profile profile;
AllocationFilter filter(isolate->main_port(), closure_class.id());
filter.set_enable_vm_ticks(true);
@@ -1161,6 +1185,7 @@ ISOLATE_UNIT_TEST_CASE(Profiler_TypedArrayAllocation) {
{
StackZone zone(thread);
HANDLESCOPE(thread);
Profile profile;
AllocationFilter filter(isolate->main_port(), float32_list_class.id());
profile.Build(thread, &filter, Profiler::sample_block_buffer());
@@ -1173,6 +1198,7 @@ ISOLATE_UNIT_TEST_CASE(Profiler_TypedArrayAllocation) {
{
StackZone zone(thread);
HANDLESCOPE(thread);
Profile profile;
AllocationFilter filter(isolate->main_port(), float32_list_class.id());
profile.Build(thread, &filter, Profiler::sample_block_buffer());
@@ -1194,6 +1220,7 @@ ISOLATE_UNIT_TEST_CASE(Profiler_TypedArrayAllocation) {
{
StackZone zone(thread);
HANDLESCOPE(thread);
Profile profile;
AllocationFilter filter(isolate->main_port(), float32_list_class.id());
profile.Build(thread, &filter, Profiler::sample_block_buffer());
@@ -1206,6 +1233,7 @@ ISOLATE_UNIT_TEST_CASE(Profiler_TypedArrayAllocation) {
{
StackZone zone(thread);
HANDLESCOPE(thread);
Profile profile;
AllocationFilter filter(isolate->main_port(), float32_list_class.id());
profile.Build(thread, &filter, Profiler::sample_block_buffer());
@@ -1237,6 +1265,7 @@ ISOLATE_UNIT_TEST_CASE(Profiler_StringAllocation) {
{
StackZone zone(thread);
HANDLESCOPE(thread);
Profile profile;
AllocationFilter filter(isolate->main_port(), one_byte_string_class.id());
profile.Build(thread, &filter, Profiler::sample_block_buffer());
@@ -1249,6 +1278,7 @@ ISOLATE_UNIT_TEST_CASE(Profiler_StringAllocation) {
{
StackZone zone(thread);
HANDLESCOPE(thread);
Profile profile;
AllocationFilter filter(isolate->main_port(), one_byte_string_class.id());
profile.Build(thread, &filter, Profiler::sample_block_buffer());
@@ -1268,6 +1298,7 @@ ISOLATE_UNIT_TEST_CASE(Profiler_StringAllocation) {
{
StackZone zone(thread);
HANDLESCOPE(thread);
Profile profile;
AllocationFilter filter(isolate->main_port(), one_byte_string_class.id());
profile.Build(thread, &filter, Profiler::sample_block_buffer());
@@ -1280,6 +1311,7 @@ ISOLATE_UNIT_TEST_CASE(Profiler_StringAllocation) {
{
StackZone zone(thread);
HANDLESCOPE(thread);
Profile profile;
AllocationFilter filter(isolate->main_port(), one_byte_string_class.id());
profile.Build(thread, &filter, Profiler::sample_block_buffer());
@@ -1311,6 +1343,7 @@ ISOLATE_UNIT_TEST_CASE(Profiler_StringInterpolation) {
{
StackZone zone(thread);
HANDLESCOPE(thread);
Profile profile;
AllocationFilter filter(isolate->main_port(), one_byte_string_class.id());
profile.Build(thread, &filter, Profiler::sample_block_buffer());
@@ -1323,6 +1356,7 @@ ISOLATE_UNIT_TEST_CASE(Profiler_StringInterpolation) {
{
StackZone zone(thread);
HANDLESCOPE(thread);
Profile profile;
AllocationFilter filter(isolate->main_port(), one_byte_string_class.id());
profile.Build(thread, &filter, Profiler::sample_block_buffer());
@@ -1348,6 +1382,7 @@ ISOLATE_UNIT_TEST_CASE(Profiler_StringInterpolation) {
{
StackZone zone(thread);
HANDLESCOPE(thread);
Profile profile;
AllocationFilter filter(isolate->main_port(), one_byte_string_class.id());
profile.Build(thread, &filter, Profiler::sample_block_buffer());
@@ -1360,6 +1395,7 @@ ISOLATE_UNIT_TEST_CASE(Profiler_StringInterpolation) {
{
StackZone zone(thread);
HANDLESCOPE(thread);
Profile profile;
AllocationFilter filter(isolate->main_port(), one_byte_string_class.id());
profile.Build(thread, &filter, Profiler::sample_block_buffer());
@@ -1415,6 +1451,7 @@ ISOLATE_UNIT_TEST_CASE(Profiler_FunctionInline) {
Thread* thread = Thread::Current();
Isolate* isolate = thread->isolate();
StackZone zone(thread);
HANDLESCOPE(thread);
Profile profile;
AllocationFilter filter(isolate->main_port(), class_a.id());
profile.Build(thread, &filter, Profiler::sample_block_buffer());
@@ -1432,6 +1469,7 @@ ISOLATE_UNIT_TEST_CASE(Profiler_FunctionInline) {
Thread* thread = Thread::Current();
Isolate* isolate = thread->isolate();
StackZone zone(thread);
HANDLESCOPE(thread);
Profile profile;
AllocationFilter filter(isolate->main_port(), class_a.id());
profile.Build(thread, &filter, Profiler::sample_block_buffer());
@@ -1560,6 +1598,7 @@ ISOLATE_UNIT_TEST_CASE(Profiler_InliningIntervalBoundry) {
Thread* thread = Thread::Current();
Isolate* isolate = thread->isolate();
StackZone zone(thread);
HANDLESCOPE(thread);
Profile profile;
AllocationFilter filter(isolate->main_port(), class_a.id());
profile.Build(thread, &filter, Profiler::sample_block_buffer());
@@ -1576,6 +1615,7 @@ ISOLATE_UNIT_TEST_CASE(Profiler_InliningIntervalBoundry) {
Thread* thread = Thread::Current();
Isolate* isolate = thread->isolate();
StackZone zone(thread);
HANDLESCOPE(thread);
Profile profile;
AllocationFilter filter(isolate->main_port(), class_a.id());
profile.Build(thread, &filter, Profiler::sample_block_buffer());
@@ -1651,6 +1691,7 @@ ISOLATE_UNIT_TEST_CASE(Profiler_ChainedSamples) {
Thread* thread = Thread::Current();
Isolate* isolate = thread->isolate();
StackZone zone(thread);
HANDLESCOPE(thread);
Profile profile;
AllocationFilter filter(isolate->main_port(), class_a.id());
profile.Build(thread, &filter, Profiler::sample_block_buffer());
@@ -1745,6 +1786,7 @@ ISOLATE_UNIT_TEST_CASE(Profiler_BasicSourcePosition) {
Thread* thread = Thread::Current();
Isolate* isolate = thread->isolate();
StackZone zone(thread);
HANDLESCOPE(thread);
Profile profile;
AllocationFilter filter(isolate->main_port(), class_a.id());
profile.Build(thread, &filter, Profiler::sample_block_buffer());
@@ -1826,6 +1868,7 @@ ISOLATE_UNIT_TEST_CASE(Profiler_BasicSourcePositionOptimized) {
Thread* thread = Thread::Current();
Isolate* isolate = thread->isolate();
StackZone zone(thread);
HANDLESCOPE(thread);
Profile profile;
AllocationFilter filter(isolate->main_port(), class_a.id());
profile.Build(thread, &filter, Profiler::sample_block_buffer());
@@ -1903,6 +1946,7 @@ ISOLATE_UNIT_TEST_CASE(Profiler_SourcePosition) {
Thread* thread = Thread::Current();
Isolate* isolate = thread->isolate();
StackZone zone(thread);
HANDLESCOPE(thread);
Profile profile;
AllocationFilter filter(isolate->main_port(), class_a.id());
profile.Build(thread, &filter, Profiler::sample_block_buffer());
@@ -2012,6 +2056,7 @@ ISOLATE_UNIT_TEST_CASE(Profiler_SourcePositionOptimized) {
Thread* thread = Thread::Current();
Isolate* isolate = thread->isolate();
StackZone zone(thread);
HANDLESCOPE(thread);
Profile profile;
AllocationFilter filter(isolate->main_port(), class_a.id());
profile.Build(thread, &filter, Profiler::sample_block_buffer());
@@ -2106,6 +2151,7 @@ ISOLATE_UNIT_TEST_CASE(Profiler_BinaryOperatorSourcePosition) {
Thread* thread = Thread::Current();
Isolate* isolate = thread->isolate();
StackZone zone(thread);
HANDLESCOPE(thread);
Profile profile;
AllocationFilter filter(isolate->main_port(), class_a.id());
profile.Build(thread, &filter, Profiler::sample_block_buffer());
@@ -2223,6 +2269,7 @@ ISOLATE_UNIT_TEST_CASE(Profiler_BinaryOperatorSourcePositionOptimized) {
Thread* thread = Thread::Current();
Isolate* isolate = thread->isolate();
StackZone zone(thread);
HANDLESCOPE(thread);
Profile profile;
AllocationFilter filter(isolate->main_port(), class_a.id());
profile.Build(thread, &filter, Profiler::sample_block_buffer());
+1
View File
@@ -1504,6 +1504,7 @@ class ProgramHashVisitor : public CodeVisitor {
uint32_t ProgramVisitor::Hash(Thread* thread) {
StackZone stack_zone(thread);
HANDLESCOPE(thread);
Zone* zone = thread->zone();
ProgramHashVisitor visitor(zone);
+2
View File
@@ -3265,6 +3265,7 @@ DEFINE_LEAF_RUNTIME_ENTRY(intptr_t,
Thread* thread = Thread::Current();
Isolate* isolate = thread->isolate();
StackZone zone(thread);
HANDLESCOPE(thread);
// All registers have been saved below last-fp as if they were locals.
const uword last_fp =
@@ -3336,6 +3337,7 @@ DEFINE_LEAF_RUNTIME_ENTRY(void, DeoptimizeFillFrame, 1, uword last_fp) {
Thread* thread = Thread::Current();
Isolate* isolate = thread->isolate();
StackZone zone(thread);
HANDLESCOPE(thread);
DeoptContext* deopt_context = isolate->deopt_context();
DartFrameIterator iterator(last_fp, thread,
+1
View File
@@ -120,6 +120,7 @@ class RuntimeEntry : public BaseRuntimeEntry {
Isolate* isolate = thread->isolate(); \
TransitionGeneratedToVM transition(thread); \
StackZone zone(thread); \
HANDLESCOPE(thread); \
CHECK_SIMULATOR_STACK_OVERFLOW(); \
if (FLAG_deoptimize_on_runtime_call_every > 0) { \
OnEveryRuntimeEntryCall(thread, "" #name, can_lazy_deopt); \
+7
View File
@@ -844,6 +844,7 @@ void Service::PostError(const String& method_name,
const Error& error) {
Thread* T = Thread::Current();
StackZone zone(T);
HANDLESCOPE(T);
JSONStream js;
js.Setup(zone.GetZone(), SendPort::Cast(reply_port).Id(), id, method_name,
parameter_keys, parameter_values);
@@ -864,6 +865,7 @@ ErrorPtr Service::InvokeMethod(Isolate* I,
{
StackZone zone(T);
HANDLESCOPE(T);
Instance& reply_port = Instance::Handle(Z);
Instance& seq = String::Handle(Z);
@@ -3225,6 +3227,7 @@ static void GetInstances(Thread* thread, JSONStream* js) {
// Ensure the array and handles created below are promptly destroyed.
StackZone zone(thread);
HANDLESCOPE(thread);
ZoneGrowableHandlePtrArray<Object> storage(thread->zone(), limit);
GetInstancesVisitor visitor(&storage, limit);
@@ -3275,6 +3278,7 @@ static void GetInstancesAsArray(Thread* thread, JSONStream* js) {
Array& instances = Array::Handle();
{
StackZone zone(thread);
HANDLESCOPE(thread);
ZoneGrowableHandlePtrArray<Object> storage(thread->zone(), 1024);
GetInstancesVisitor visitor(&storage, kSmiMax);
@@ -3302,6 +3306,7 @@ static const MethodParameter* const get_ports_params[] = {
static void GetPorts(Thread* thread, JSONStream* js) {
// Ensure the array and handles created below are promptly destroyed.
StackZone zone(thread);
HANDLESCOPE(thread);
const GrowableObjectArray& ports = GrowableObjectArray::Handle(
GrowableObjectArray::RawCast(DartLibraryCalls::LookupOpenPorts()));
JSONObject jsobj(js);
@@ -4885,6 +4890,8 @@ void Service::PrintJSONForVM(JSONStream* js, bool ref) {
jsobj.AddProperty("targetCPU", CPU::Id());
jsobj.AddProperty("version", Version::String());
jsobj.AddProperty("_profilerMode", FLAG_profile_vm ? "VM" : "Dart");
jsobj.AddProperty64("_nativeZoneMemoryUsage",
ApiNativeScope::current_memory_usage());
jsobj.AddProperty64("pid", OS::ProcessId());
jsobj.AddPropertyTimeMillis(
"startTime", OS::GetCurrentTimeMillis() - Dart::UptimeMillis());
+1
View File
@@ -438,6 +438,7 @@ class RunServiceTask : public ThreadPool::Task {
Thread* T = Thread::Current();
ASSERT(I == T->isolate());
StackZone zone(T);
HANDLESCOPE(T);
// Invoke main which will set up the service port.
const Library& root_library =
Library::Handle(Z, I->group()->object_store()->root_library());
+15 -1
View File
@@ -9,7 +9,21 @@
namespace dart {
ThreadState::ThreadState(bool is_os_thread) : BaseThread(is_os_thread) {}
ThreadState::ThreadState(bool is_os_thread) : BaseThread(is_os_thread) {
// This thread should not yet own any zones. If it does, we need to make sure
// we've accounted for any memory it has already allocated.
if (zone_ == nullptr) {
ASSERT(current_zone_capacity_ == 0);
} else {
Zone* current = zone_;
uintptr_t total_zone_capacity = 0;
while (current != nullptr) {
total_zone_capacity += current->CapacityInBytes();
current = current->previous();
}
ASSERT(current_zone_capacity_ == total_zone_capacity);
}
}
ThreadState::~ThreadState() {}
+12
View File
@@ -40,6 +40,17 @@ class ThreadState : public BaseThread {
bool ZoneIsOwnedByThread(Zone* zone) const;
void IncrementMemoryCapacity(uintptr_t value) {
current_zone_capacity_ += value;
}
void DecrementMemoryCapacity(uintptr_t value) {
ASSERT(current_zone_capacity_ >= value);
current_zone_capacity_ -= value;
}
uintptr_t current_zone_capacity() const { return current_zone_capacity_; }
StackResource* top_resource() const { return top_resource_; }
void set_top_resource(StackResource* value) { top_resource_ = value; }
static intptr_t top_resource_offset() {
@@ -75,6 +86,7 @@ class ThreadState : public BaseThread {
OSThread* os_thread_ = nullptr;
Zone* zone_ = nullptr;
uintptr_t current_zone_capacity_ = 0;
StackResource* top_resource_ = nullptr;
LongJumpScope* long_jump_base_ = nullptr;
+6
View File
@@ -121,6 +121,7 @@ class TaskWithZoneAllocation : public ThreadPool::Task {
Thread* thread = Thread::Current();
// Create a zone (which is also a stack resource) and exercise it a bit.
StackZone stack_zone(thread);
HANDLESCOPE(thread);
Zone* zone = thread->zone();
EXPECT_EQ(zone, stack_zone.GetZone());
ZoneGrowableArray<bool>* a0 = new (zone) ZoneGrowableArray<bool>(zone, 1);
@@ -254,6 +255,7 @@ class SimpleTaskWithZoneAllocation : public ThreadPool::Task {
*thread_ptr_ = thread;
StackZone stack_zone(thread);
HANDLESCOPE(thread);
Zone* zone = thread->zone();
EXPECT_EQ(zone, stack_zone.GetZone());
@@ -388,6 +390,7 @@ class ICDataTestTask : public ThreadPool::Task {
{
StackZone stack_zone(thread);
HANDLESCOPE(thread);
ICData& ic_data = ICData::Handle();
Array& arr = Array::Handle();
@@ -533,6 +536,7 @@ class SafepointTestTask : public ThreadPool::Task {
for (int i = reinterpret_cast<intptr_t>(thread);; ++i) {
StackZone stack_zone(thread);
Zone* zone = thread->zone();
HANDLESCOPE(thread);
const intptr_t kUniqueSmi = 928327281;
Smi& smi = Smi::Handle(zone, Smi::New(kUniqueSmi));
if ((i % 100) != 0) {
@@ -848,6 +852,7 @@ class AllocAndGCTask : public ThreadPool::Task {
Thread* thread = Thread::Current();
StackZone stack_zone(thread);
Zone* zone = stack_zone.GetZone();
HANDLESCOPE(thread);
String& old_str = String::Handle(zone, String::New("old", Heap::kOld));
isolate_->group()->heap()->CollectAllGarbage();
EXPECT(old_str.Equals("old"));
@@ -895,6 +900,7 @@ class AllocateGlobsOfMemoryTask : public ThreadPool::Task {
Thread* thread = Thread::Current();
StackZone stack_zone(thread);
Zone* zone = stack_zone.GetZone();
HANDLESCOPE(thread);
int count = 100 * 1000;
while (count-- > 0) {
String::Handle(zone, String::New("abc"));
+77 -31
View File
@@ -33,6 +33,8 @@ class Zone::Segment {
// Allocate or delete individual segments.
static Segment* New(intptr_t size, Segment* next);
static void DeleteSegmentList(Segment* segment);
static void IncrementMemoryCapacity(uintptr_t size);
static void DecrementMemoryCapacity(uintptr_t size);
private:
Segment* next_;
@@ -105,6 +107,7 @@ Zone::Segment* Zone::Segment::New(intptr_t size, Zone::Segment* next) {
LSAN_REGISTER_ROOT_REGION(result, sizeof(*result));
IncrementMemoryCapacity(size);
return result;
}
@@ -112,6 +115,7 @@ void Zone::Segment::DeleteSegmentList(Segment* head) {
Segment* current = head;
while (current != NULL) {
intptr_t size = current->size();
DecrementMemoryCapacity(size);
Segment* next = current->next();
VirtualMemory* memory = current->memory();
#ifdef DEBUG
@@ -137,13 +141,38 @@ void Zone::Segment::DeleteSegmentList(Segment* head) {
}
}
void Zone::Segment::IncrementMemoryCapacity(uintptr_t size) {
ThreadState* current_thread = ThreadState::Current();
if (current_thread != NULL) {
current_thread->IncrementMemoryCapacity(size);
} else if (ApiNativeScope::Current() != NULL) {
// If there is no current thread, we might be inside of a native scope.
ApiNativeScope::IncrementNativeScopeMemoryCapacity(size);
}
}
void Zone::Segment::DecrementMemoryCapacity(uintptr_t size) {
ThreadState* current_thread = ThreadState::Current();
if (current_thread != NULL) {
current_thread->DecrementMemoryCapacity(size);
} else if (ApiNativeScope::Current() != NULL) {
// If there is no current thread, we might be inside of a native scope.
ApiNativeScope::DecrementNativeScopeMemoryCapacity(size);
}
}
// TODO(bkonyi): We need to account for the initial chunk size when a new zone
// is created within a new thread or ApiNativeScope when calculating high
// watermarks or memory consumption.
Zone::Zone()
: position_(reinterpret_cast<uword>(&buffer_)),
limit_(position_ + kInitialChunkSize),
segments_(nullptr),
previous_(nullptr),
head_(NULL),
large_segments_(NULL),
previous_(NULL),
handles_() {
ASSERT(Utils::IsAligned(position_, kAlignment));
Segment::IncrementMemoryCapacity(kInitialChunkSize);
#ifdef DEBUG
// Zap the entire initial buffer.
memset(&buffer_, kZapUninitializedByte, kInitialChunkSize);
@@ -152,64 +181,70 @@ Zone::Zone()
Zone::~Zone() {
if (FLAG_trace_zones) {
Print();
DumpZoneSizes();
}
Segment::DeleteSegmentList(segments_);
DeleteAll();
Segment::DecrementMemoryCapacity(kInitialChunkSize);
}
void Zone::Reset() {
void Zone::DeleteAll() {
// Traverse the chained list of segments, zapping (in debug mode)
// and freeing every zone segment.
Segment::DeleteSegmentList(segments_);
segments_ = nullptr;
if (head_ != NULL) {
Segment::DeleteSegmentList(head_);
}
if (large_segments_ != NULL) {
Segment::DeleteSegmentList(large_segments_);
}
// Reset zone state.
#ifdef DEBUG
memset(&buffer_, kZapDeletedByte, kInitialChunkSize);
#endif
position_ = reinterpret_cast<uword>(&buffer_);
limit_ = position_ + kInitialChunkSize;
small_segment_capacity_ = 0;
previous_ = nullptr;
head_ = NULL;
large_segments_ = NULL;
previous_ = NULL;
handles_.Reset();
}
uintptr_t Zone::SizeInBytes() const {
uintptr_t size = 0;
if (segments_ == nullptr) {
for (Segment* s = large_segments_; s != NULL; s = s->next()) {
size += s->size();
}
if (head_ == NULL) {
return size + (position_ - reinterpret_cast<uword>(&buffer_));
}
size += kInitialChunkSize;
for (Segment* s = segments_->next(); s != nullptr; s = s->next()) {
for (Segment* s = head_->next(); s != NULL; s = s->next()) {
size += s->size();
}
return size + (position_ - segments_->start());
return size + (position_ - head_->start());
}
uintptr_t Zone::CapacityInBytes() const {
uintptr_t size = kInitialChunkSize;
for (Segment* s = segments_; s != nullptr; s = s->next()) {
uintptr_t size = 0;
for (Segment* s = large_segments_; s != NULL; s = s->next()) {
size += s->size();
}
if (head_ == NULL) {
return size + kInitialChunkSize;
}
size += kInitialChunkSize;
for (Segment* s = head_; s != NULL; s = s->next()) {
size += s->size();
}
return size;
}
void Zone::Print() const {
intptr_t segment_size = CapacityInBytes();
intptr_t scoped_handle_size = handles_.ScopedHandlesCapacityInBytes();
intptr_t zone_handle_size = handles_.ZoneHandlesCapacityInBytes();
intptr_t total_size = segment_size + scoped_handle_size + zone_handle_size;
OS::PrintErr("Zone(%p, segments: %" Pd ", scoped_handles: %" Pd
", zone_handles: %" Pd ", total: %" Pd ")\n",
this, segment_size, scoped_handle_size, zone_handle_size,
total_size);
}
uword Zone::AllocateExpand(intptr_t size) {
ASSERT(size >= 0);
if (FLAG_trace_zones) {
OS::PrintErr("*** Expanding zone 0x%" Px "\n",
reinterpret_cast<intptr_t>(this));
Print();
DumpZoneSizes();
}
// Make sure the requested size is already properly aligned and that
// there isn't enough room in the Zone to satisfy the request.
@@ -239,13 +274,13 @@ uword Zone::AllocateExpand(intptr_t size) {
ASSERT(next_size >= kSegmentSize);
// Allocate another segment and chain it up.
segments_ = Segment::New(next_size, segments_);
head_ = Segment::New(next_size, head_);
small_segment_capacity_ += next_size;
// Recompute 'position' and 'limit' based on the new head segment.
uword result = Utils::RoundUp(segments_->start(), kAlignment);
uword result = Utils::RoundUp(head_->start(), kAlignment);
position_ = result + size;
limit_ = segments_->end();
limit_ = head_->end();
ASSERT(position_ <= limit_);
return result;
}
@@ -261,9 +296,9 @@ uword Zone::AllocateLargeSegment(intptr_t size) {
// Create a new large segment and chain it up.
// Account for book keeping fields in size.
size += Utils::RoundUp(sizeof(Segment), kAlignment);
segments_ = Segment::New(size, segments_);
large_segments_ = Segment::New(size, large_segments_);
uword result = Utils::RoundUp(segments_->start(), kAlignment);
uword result = Utils::RoundUp(large_segments_->start(), kAlignment);
return result;
}
@@ -302,6 +337,17 @@ char* Zone::ConcatStrings(const char* a, const char* b, char join) {
return copy;
}
void Zone::DumpZoneSizes() {
intptr_t size = 0;
for (Segment* s = large_segments_; s != NULL; s = s->next()) {
size += s->size();
}
OS::PrintErr("*** Zone(0x%" Px
") size in bytes,"
" Total = %" Pd " Large Segments = %" Pd "\n",
reinterpret_cast<intptr_t>(this), SizeInBytes(), size);
}
void Zone::VisitObjectPointers(ObjectPointerVisitor* visitor) {
Zone* zone = this;
while (zone != NULL) {
+10 -7
View File
@@ -67,9 +67,6 @@ class Zone {
// Computes the amount of space used in the zone.
uintptr_t CapacityInBytes() const;
// Dump the current allocated sizes in the zone object.
void Print() const;
// Structure for managing handles allocation.
VMHandles* handles() { return &handles_; }
@@ -98,7 +95,7 @@ class Zone {
~Zone(); // Delete all memory associated with the zone.
// Default initial chunk size.
static const intptr_t kInitialChunkSize = 128;
static const intptr_t kInitialChunkSize = 1 * KB;
// Default segment size.
static const intptr_t kSegmentSize = 64 * KB;
@@ -122,7 +119,7 @@ class Zone {
void Link(Zone* current_zone) { previous_ = current_zone; }
// Delete all objects and free all memory allocated in the zone.
void Reset();
void DeleteAll();
// Does not actually free any memory. Enables templated containers like
// BaseGrowableArray to use different allocators.
@@ -137,6 +134,9 @@ class Zone {
#endif
}
// Dump the current allocated sizes in the zone object.
void DumpZoneSizes();
// Overflow check (FATAL) for array length.
template <class ElementType>
static inline void CheckLength(intptr_t len);
@@ -155,8 +155,11 @@ class Zone {
// Total size of all segments in [head_].
intptr_t small_segment_capacity_ = 0;
// List of all segments allocated in this zone; may be NULL.
Segment* segments_;
// The current head segment; may be NULL.
Segment* head_;
// List of large segments allocated in this zone; may be NULL.
Segment* large_segments_;
// Used for chaining zones in order to allow unwinding of stacks.
Zone* previous_;
+15
View File
@@ -165,6 +165,21 @@ TEST_CASE(PrintToString) {
EXPECT_STREQ("Hello World!", result);
}
VM_UNIT_TEST_CASE(NativeScopeZoneAllocation) {
ASSERT(ApiNativeScope::Current() == NULL);
ASSERT(Thread::Current() == NULL);
EXPECT_EQ(0UL, ApiNativeScope::current_memory_usage());
{
ApiNativeScope scope;
EXPECT_EQ(scope.zone()->CapacityInBytes(),
ApiNativeScope::current_memory_usage());
(void)Dart_ScopeAllocate(2048);
EXPECT_EQ(scope.zone()->CapacityInBytes(),
ApiNativeScope::current_memory_usage());
}
EXPECT_EQ(0UL, ApiNativeScope::current_memory_usage());
}
#if !defined(PRODUCT)
// Allow for pooling in the malloc implementation.
static const int64_t kRssSlack = 20 * MB;