test-alloc.cc 7.2 KB
Newer Older
1
// Copyright 2012 the V8 project authors. All rights reserved.
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
//       copyright notice, this list of conditions and the following
//       disclaimer in the documentation and/or other materials provided
//       with the distribution.
//     * Neither the name of Google Inc. nor the names of its
//       contributors may be used to endorse or promote products derived
//       from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

28
#include "src/init/v8.h"
29 30
#include "test/cctest/cctest.h"

31
#include "src/api/api-inl.h"
32
#include "src/builtins/accessors.h"
33
#include "src/heap/heap-inl.h"
34
#include "src/objects/api-callbacks.h"
35
#include "src/objects/objects-inl.h"
36
#include "src/objects/property.h"
37
#include "test/cctest/heap/heap-tester.h"
38
#include "test/cctest/heap/heap-utils.h"
39

40 41 42
namespace v8 {
namespace internal {
namespace heap {
43

44 45 46 47 48
Handle<Object> HeapTester::TestAllocateAfterFailures() {
  // Similar to what the factory's retrying logic does in the last-resort case,
  // we wrap the allocator function in an AlwaysAllocateScope.  Test that
  // all allocations succeed immediately without any retry.
  CcTest::CollectAllAvailableGarbage();
49
  Heap* heap = CcTest::heap();
50
  AlwaysAllocateScopeForTesting scope(heap);
51
  int size = FixedArray::SizeFor(100);
52 53 54
  // Young generation.
  HeapObject obj =
      heap->AllocateRaw(size, AllocationType::kYoung).ToObjectChecked();
55 56
  // In order to pass heap verification on Isolate teardown, mark the
  // allocated area as a filler.
57
  heap->CreateFillerObjectAt(obj.address(), size, ClearRecordedSlots::kNo);
58

59
  // Old generation.
60
  heap::SimulateFullSpace(heap->old_space());
61
  obj = heap->AllocateRaw(size, AllocationType::kOld).ToObjectChecked();
62
  heap->CreateFillerObjectAt(obj.address(), size, ClearRecordedSlots::kNo);
63

64
  // Large object space.
65 66 67 68 69 70
  static const size_t kLargeObjectSpaceFillerLength =
      3 * (Page::kPageSize / 10);
  static const size_t kLargeObjectSpaceFillerSize =
      FixedArray::SizeFor(kLargeObjectSpaceFillerLength);
  CHECK_GT(kLargeObjectSpaceFillerSize,
           static_cast<size_t>(heap->old_space()->AreaSize()));
71
  while (heap->OldGenerationSpaceAvailable() > kLargeObjectSpaceFillerSize) {
72
    obj = heap->AllocateRaw(kLargeObjectSpaceFillerSize, AllocationType::kOld)
73
              .ToObjectChecked();
74
    heap->CreateFillerObjectAt(obj.address(), size, ClearRecordedSlots::kNo);
75
  }
76
  obj = heap->AllocateRaw(kLargeObjectSpaceFillerSize, AllocationType::kOld)
77
            .ToObjectChecked();
78
  heap->CreateFillerObjectAt(obj.address(), size, ClearRecordedSlots::kNo);
79 80

  // Map space.
81
  heap::SimulateFullSpace(heap->map_space());
82
  obj = heap->AllocateRaw(Map::kSize, AllocationType::kMap).ToObjectChecked();
83 84
  heap->CreateFillerObjectAt(obj.address(), Map::kSize,
                             ClearRecordedSlots::kNo);
85

86
  // Code space.
87
  heap::SimulateFullSpace(heap->code_space());
88
  size = CcTest::i_isolate()->builtins()->builtin(Builtins::kIllegal).Size();
89
  obj =
90
      heap->AllocateRaw(size, AllocationType::kCode, AllocationOrigin::kRuntime)
91
          .ToObjectChecked();
92
  heap->CreateFillerObjectAt(obj.address(), size, ClearRecordedSlots::kNo);
93
  return CcTest::i_isolate()->factory()->true_value();
94 95 96
}


97
HEAP_TEST(StressHandles) {
98 99
  // For TestAllocateAfterFailures.
  FLAG_stress_concurrent_allocation = false;
100
  v8::HandleScope scope(CcTest::isolate());
101
  v8::Local<v8::Context> env = v8::Context::New(CcTest::isolate());
102
  env->Enter();
103
  Handle<Object> o = TestAllocateAfterFailures();
104
  CHECK(o->IsTrue(CcTest::i_isolate()));
105 106
  env->Exit();
}
107 108


109
void TestGetter(
110
    v8::Local<v8::Name> name,
111 112 113
    const v8::PropertyCallbackInfo<v8::Value>& info) {
  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
  HandleScope scope(isolate);
114 115
  info.GetReturnValue().Set(
      v8::Utils::ToLocal(HeapTester::TestAllocateAfterFailures()));
116 117
}

118 119
void TestSetter(v8::Local<v8::Name> name, v8::Local<v8::Value> value,
                const v8::PropertyCallbackInfo<v8::Boolean>& info) {
120 121 122 123 124 125
  UNREACHABLE();
}


Handle<AccessorInfo> TestAccessorInfo(
      Isolate* isolate, PropertyAttributes attributes) {
126
  Handle<String> name = isolate->factory()->NewStringFromStaticChars("get");
127
  return Accessors::MakeAccessor(isolate, name, &TestGetter, &TestSetter);
128
}
129 130 131


TEST(StressJS) {
132 133
  // For TestAllocateAfterFailures in TestGetter.
  FLAG_stress_concurrent_allocation = false;
134
  Isolate* isolate = CcTest::i_isolate();
135
  Factory* factory = isolate->factory();
136
  v8::HandleScope scope(CcTest::isolate());
137
  v8::Local<v8::Context> env = v8::Context::New(CcTest::isolate());
138
  env->Enter();
139 140 141 142 143

  NewFunctionArgs args = NewFunctionArgs::ForBuiltin(
      factory->function_string(), isolate->sloppy_function_map(),
      Builtins::kEmptyFunction);
  Handle<JSFunction> function = factory->NewFunction(args);
144
  CHECK(!function->shared().construct_as_builtin());
145 146

  // Force the creation of an initial map.
147
  factory->NewJSObject(function);
148

149
  // Patch the map to have an accessor for "get".
150
  Handle<Map> map(function->initial_map(), isolate);
151 152
  Handle<DescriptorArray> instance_descriptors(
      map->instance_descriptors(kRelaxedLoad), isolate);
153
  CHECK_EQ(0, instance_descriptors->number_of_descriptors());
154

155
  PropertyAttributes attrs = NONE;
156
  Handle<AccessorInfo> foreign = TestAccessorInfo(isolate, attrs);
157
  Map::EnsureDescriptorSlack(isolate, map, 1);
158

159
  Descriptor d = Descriptor::AccessorConstant(
160
      Handle<Name>(Name::cast(foreign->name()), isolate), foreign, attrs);
161
  map->AppendDescriptor(isolate, &d);
162

163
  // Add the Foo constructor the global object.
164
  CHECK(env->Global()
165
            ->Set(env, v8::String::NewFromUtf8Literal(CcTest::isolate(), "Foo"),
166 167
                  v8::Utils::CallableToLocal(function))
            .FromJust());
168
  // Call the accessor through JavaScript.
169
  v8::Local<v8::Value> result =
170 171
      v8::Script::Compile(env, v8::String::NewFromUtf8Literal(CcTest::isolate(),
                                                              "(new Foo).get"))
172 173 174
          .ToLocalChecked()
          ->Run(env)
          .ToLocalChecked();
175
  CHECK_EQ(true, result->BooleanValue(CcTest::isolate()));
176 177
  env->Exit();
}
178

179 180 181
}  // namespace heap
}  // namespace internal
}  // namespace v8