blob: 21b50c0076cd2c4efc69e2011678f226092c406c [file] [log] [blame]
// 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 "platform/assert.h"
#include "vm/dart.h"
#include "vm/isolate.h"
#include "vm/unit_test.h"
#include "vm/zone.h"
namespace dart {
UNIT_TEST_CASE(AllocateZone) {
#if defined(DEBUG)
FLAG_trace_zones = true;
#endif
Dart_CreateIsolate(NULL, NULL, bin::core_isolate_snapshot_data,
bin::core_isolate_snapshot_instructions, NULL, NULL, NULL);
Thread* thread = Thread::Current();
EXPECT(thread->zone() == NULL);
{
StackZone stack_zone(thread);
EXPECT(thread->zone() != NULL);
Zone* zone = stack_zone.GetZone();
intptr_t allocated_size = 0;
// The loop is to make sure we overflow one segment and go on
// to the next segment.
for (int i = 0; i < 1000; i++) {
uword first = zone->AllocUnsafe(2 * kWordSize);
uword second = zone->AllocUnsafe(3 * kWordSize);
EXPECT(first != second);
allocated_size = ((2 + 3) * kWordSize);
}
EXPECT_LE(allocated_size, zone->SizeInBytes());
// Test for allocation of large segments.
const uword kLargeSize = 1 * MB;
const uword kSegmentSize = 64 * KB;
ASSERT(kLargeSize > kSegmentSize);
for (int i = 0; i < 10; i++) {
EXPECT(zone->AllocUnsafe(kLargeSize) != 0);
allocated_size += kLargeSize;
}
EXPECT_LE(allocated_size, zone->SizeInBytes());
// Test corner cases of kSegmentSize.
uint8_t* buffer = NULL;
buffer =
reinterpret_cast<uint8_t*>(zone->AllocUnsafe(kSegmentSize - kWordSize));
EXPECT(buffer != NULL);
buffer[(kSegmentSize - kWordSize) - 1] = 0;
allocated_size += (kSegmentSize - kWordSize);
EXPECT_LE(allocated_size, zone->SizeInBytes());
buffer = reinterpret_cast<uint8_t*>(
zone->AllocUnsafe(kSegmentSize - (2 * kWordSize)));
EXPECT(buffer != NULL);
buffer[(kSegmentSize - (2 * kWordSize)) - 1] = 0;
allocated_size += (kSegmentSize - (2 * kWordSize));
EXPECT_LE(allocated_size, zone->SizeInBytes());
buffer =
reinterpret_cast<uint8_t*>(zone->AllocUnsafe(kSegmentSize + kWordSize));
EXPECT(buffer != NULL);
buffer[(kSegmentSize + kWordSize) - 1] = 0;
allocated_size += (kSegmentSize + kWordSize);
EXPECT_LE(allocated_size, zone->SizeInBytes());
}
EXPECT(thread->zone() == NULL);
Dart_ShutdownIsolate();
}
UNIT_TEST_CASE(AllocGeneric_Success) {
#if defined(DEBUG)
FLAG_trace_zones = true;
#endif
Dart_CreateIsolate(NULL, NULL, bin::core_isolate_snapshot_data,
bin::core_isolate_snapshot_instructions, NULL, NULL, NULL);
Thread* thread = Thread::Current();
EXPECT(thread->zone() == NULL);
{
StackZone zone(thread);
EXPECT(thread->zone() != NULL);
intptr_t allocated_size = 0;
const intptr_t kNumElements = 1000;
zone.GetZone()->Alloc<uint32_t>(kNumElements);
allocated_size += sizeof(uint32_t) * kNumElements;
EXPECT_LE(allocated_size, zone.SizeInBytes());
}
EXPECT(thread->zone() == NULL);
Dart_ShutdownIsolate();
}
// This test is expected to crash.
UNIT_TEST_CASE(AllocGeneric_Overflow) {
#if defined(DEBUG)
FLAG_trace_zones = true;
#endif
Dart_CreateIsolate(NULL, NULL, bin::core_isolate_snapshot_data,
bin::core_isolate_snapshot_instructions, NULL, NULL, NULL);
Thread* thread = Thread::Current();
EXPECT(thread->zone() == NULL);
{
StackZone zone(thread);
EXPECT(thread->zone() != NULL);
const intptr_t kNumElements = (kIntptrMax / sizeof(uint32_t)) + 1;
zone.GetZone()->Alloc<uint32_t>(kNumElements);
}
Dart_ShutdownIsolate();
}
UNIT_TEST_CASE(ZoneAllocated) {
#if defined(DEBUG)
FLAG_trace_zones = true;
#endif
Dart_CreateIsolate(NULL, NULL, bin::core_isolate_snapshot_data,
bin::core_isolate_snapshot_instructions, NULL, NULL, NULL);
Thread* thread = Thread::Current();
EXPECT(thread->zone() == NULL);
static int marker;
class SimpleZoneObject : public ZoneAllocated {
public:
SimpleZoneObject() : slot(marker++) {}
virtual ~SimpleZoneObject() {}
virtual int GetSlot() { return slot; }
int slot;
};
// Reset the marker.
marker = 0;
// Create a few zone allocated objects.
{
StackZone zone(thread);
EXPECT_EQ(0, zone.SizeInBytes());
SimpleZoneObject* first = new SimpleZoneObject();
EXPECT(first != NULL);
SimpleZoneObject* second = new SimpleZoneObject();
EXPECT(second != NULL);
EXPECT(first != second);
intptr_t expected_size = (2 * sizeof(SimpleZoneObject));
EXPECT_LE(expected_size, zone.SizeInBytes());
// Make sure the constructors were invoked.
EXPECT_EQ(0, first->slot);
EXPECT_EQ(1, second->slot);
// Make sure we can write to the members of the zone objects.
first->slot = 42;
second->slot = 87;
EXPECT_EQ(42, first->slot);
EXPECT_EQ(87, second->slot);
}
EXPECT(thread->zone() == NULL);
Dart_ShutdownIsolate();
}
TEST_CASE(PrintToString) {
StackZone zone(Thread::Current());
const char* result = zone.GetZone()->PrintToString("Hello %s!", "World");
EXPECT_STREQ("Hello World!", result);
}
#ifndef PRODUCT
UNIT_TEST_CASE(PrintZoneMemoryInfoToJSON) {
#if defined(DEBUG)
FLAG_trace_zones = true;
#endif
Dart_CreateIsolate(NULL, NULL, bin::core_isolate_snapshot_data,
bin::core_isolate_snapshot_instructions, NULL, NULL, NULL);
Thread* thread = Thread::Current();
EXPECT(thread->zone() == NULL);
{
StackZone zone(thread);
StackZone string_stack_zone(thread);
EXPECT(thread->zone() != NULL);
intptr_t allocated_size = 0;
const intptr_t kNumElements = 1000;
zone.GetZone()->Alloc<uint32_t>(kNumElements);
allocated_size += sizeof(uint32_t) * kNumElements;
EXPECT_LE(allocated_size, zone.SizeInBytes());
{
JSONStream stream;
// Get the JSON formated zone information.
zone.GetZone()->PrintJSON(&stream);
const char* json = stream.ToCString();
// Ensure that matches actual values.
char* size_buf =
OS::SCreate(string_stack_zone.GetZone(), "\"capacity\":%" Pd
","
"\"used\":%" Pd "",
zone.CapacityInBytes(), zone.SizeInBytes());
EXPECT_LE(zone.SizeInBytes(), zone.CapacityInBytes());
EXPECT_SUBSTRING(size_buf, json);
}
// Expand the zone to ensure that JSON is updated accordingly.
zone.GetZone()->Alloc<uint32_t>(kNumElements);
allocated_size += sizeof(uint32_t) * kNumElements;
EXPECT_LE(allocated_size, zone.SizeInBytes());
{
JSONStream stream;
zone.GetZone()->PrintJSON(&stream);
const char* json = stream.ToCString();
char* size_buf =
OS::SCreate(string_stack_zone.GetZone(), "\"capacity\":%" Pd
","
"\"used\":%" Pd "",
zone.CapacityInBytes(), zone.SizeInBytes());
EXPECT_LE(zone.SizeInBytes(), zone.CapacityInBytes());
EXPECT_SUBSTRING(size_buf, json);
}
}
EXPECT(thread->zone() == NULL);
Dart_ShutdownIsolate();
}
#endif
UNIT_TEST_CASE(NativeScopeZoneAllocation) {
ASSERT(ApiNativeScope::Current() == NULL);
ASSERT(Thread::Current() == NULL);
EXPECT_EQ(0, 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(0, ApiNativeScope::current_memory_usage());
}
} // namespace dart