The data contained in this repository can be downloaded to your computer using one of several clients.
Please see the documentation of your version control software client for more information.

Please select the desired protocol below to get the URL.

This URL has Read-Only access.

Statistics
| Branch: | Revision:

main_repo / deps / v8 / test / cctest / test-alloc.cc @ f230a1cf

History | View | Annotate | Download (8.21 KB)

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

    
28
#include "v8.h"
29
#include "accessors.h"
30

    
31
#include "cctest.h"
32

    
33

    
34
using namespace v8::internal;
35

    
36

    
37
static MaybeObject* AllocateAfterFailures() {
38
  static int attempts = 0;
39
  if (++attempts < 3) return Failure::RetryAfterGC();
40
  Heap* heap = CcTest::heap();
41

    
42
  // New space.
43
  SimulateFullSpace(heap->new_space());
44
  CHECK(!heap->AllocateByteArray(100)->IsFailure());
45
  CHECK(!heap->AllocateFixedArray(100, NOT_TENURED)->IsFailure());
46

    
47
  // Make sure we can allocate through optimized allocation functions
48
  // for specific kinds.
49
  CHECK(!heap->AllocateFixedArray(100)->IsFailure());
50
  CHECK(!heap->AllocateHeapNumber(0.42)->IsFailure());
51
  CHECK(!heap->AllocateArgumentsObject(Smi::FromInt(87), 10)->IsFailure());
52
  Object* object = heap->AllocateJSObject(
53
      *CcTest::i_isolate()->object_function())->ToObjectChecked();
54
  CHECK(!heap->CopyJSObject(JSObject::cast(object))->IsFailure());
55

    
56
  // Old data space.
57
  SimulateFullSpace(heap->old_data_space());
58
  CHECK(!heap->AllocateRawOneByteString(100, TENURED)->IsFailure());
59

    
60
  // Old pointer space.
61
  SimulateFullSpace(heap->old_pointer_space());
62
  CHECK(!heap->AllocateFixedArray(10000, TENURED)->IsFailure());
63

    
64
  // Large object space.
65
  static const int kLargeObjectSpaceFillerLength = 300000;
66
  static const int kLargeObjectSpaceFillerSize = FixedArray::SizeFor(
67
      kLargeObjectSpaceFillerLength);
68
  ASSERT(kLargeObjectSpaceFillerSize > heap->old_pointer_space()->AreaSize());
69
  while (heap->OldGenerationSpaceAvailable() > kLargeObjectSpaceFillerSize) {
70
    CHECK(!heap->AllocateFixedArray(kLargeObjectSpaceFillerLength, TENURED)->
71
          IsFailure());
72
  }
73
  CHECK(!heap->AllocateFixedArray(kLargeObjectSpaceFillerLength, TENURED)->
74
        IsFailure());
75

    
76
  // Map space.
77
  SimulateFullSpace(heap->map_space());
78
  int instance_size = JSObject::kHeaderSize;
79
  CHECK(!heap->AllocateMap(JS_OBJECT_TYPE, instance_size)->IsFailure());
80

    
81
  // Test that we can allocate in old pointer space and code space.
82
  SimulateFullSpace(heap->code_space());
83
  CHECK(!heap->AllocateFixedArray(100, TENURED)->IsFailure());
84
  CHECK(!heap->CopyCode(CcTest::i_isolate()->builtins()->builtin(
85
      Builtins::kIllegal))->IsFailure());
86

    
87
  // Return success.
88
  return Smi::FromInt(42);
89
}
90

    
91

    
92
static Handle<Object> Test() {
93
  CALL_HEAP_FUNCTION(CcTest::i_isolate(), AllocateAfterFailures(), Object);
94
}
95

    
96

    
97
TEST(StressHandles) {
98
  v8::HandleScope scope(CcTest::isolate());
99
  v8::Handle<v8::Context> env = v8::Context::New(CcTest::isolate());
100
  env->Enter();
101
  Handle<Object> o = Test();
102
  CHECK(o->IsSmi() && Smi::cast(*o)->value() == 42);
103
  env->Exit();
104
}
105

    
106

    
107
static MaybeObject* TestAccessorGet(Isolate* isolate, Object* object, void*) {
108
  return AllocateAfterFailures();
109
}
110

    
111

    
112
const AccessorDescriptor kDescriptor = {
113
  TestAccessorGet,
114
  0,
115
  0
116
};
117

    
118

    
119
TEST(StressJS) {
120
  Isolate* isolate = CcTest::i_isolate();
121
  Factory* factory = isolate->factory();
122
  v8::HandleScope scope(CcTest::isolate());
123
  v8::Handle<v8::Context> env = v8::Context::New(CcTest::isolate());
124
  env->Enter();
125
  Handle<JSFunction> function =
126
      factory->NewFunction(factory->function_string(), factory->null_value());
127
  // Force the creation of an initial map and set the code to
128
  // something empty.
129
  factory->NewJSObject(function);
130
  function->ReplaceCode(CcTest::i_isolate()->builtins()->builtin(
131
      Builtins::kEmptyFunction));
132
  // Patch the map to have an accessor for "get".
133
  Handle<Map> map(function->initial_map());
134
  Handle<DescriptorArray> instance_descriptors(map->instance_descriptors());
135
  Handle<Foreign> foreign = factory->NewForeign(&kDescriptor);
136
  Handle<String> name =
137
      factory->NewStringFromAscii(Vector<const char>("get", 3));
138
  ASSERT(instance_descriptors->IsEmpty());
139

    
140
  Handle<DescriptorArray> new_descriptors = factory->NewDescriptorArray(0, 1);
141

    
142
  v8::internal::DescriptorArray::WhitenessWitness witness(*new_descriptors);
143
  map->set_instance_descriptors(*new_descriptors);
144

    
145
  CallbacksDescriptor d(*name,
146
                        *foreign,
147
                        static_cast<PropertyAttributes>(0));
148
  map->AppendDescriptor(&d, witness);
149

    
150
  // Add the Foo constructor the global object.
151
  env->Global()->Set(v8::String::New("Foo"), v8::Utils::ToLocal(function));
152
  // Call the accessor through JavaScript.
153
  v8::Handle<v8::Value> result =
154
      v8::Script::Compile(v8::String::New("(new Foo).get"))->Run();
155
  CHECK_EQ(42, result->Int32Value());
156
  env->Exit();
157
}
158

    
159

    
160
// CodeRange test.
161
// Tests memory management in a CodeRange by allocating and freeing blocks,
162
// using a pseudorandom generator to choose block sizes geometrically
163
// distributed between 2 * Page::kPageSize and 2^5 + 1 * Page::kPageSize.
164
// Ensure that the freed chunks are collected and reused by allocating (in
165
// total) more than the size of the CodeRange.
166

    
167
// This pseudorandom generator does not need to be particularly good.
168
// Use the lower half of the V8::Random() generator.
169
unsigned int Pseudorandom() {
170
  static uint32_t lo = 2345;
171
  lo = 18273 * (lo & 0xFFFF) + (lo >> 16);  // Provably not 0.
172
  return lo & 0xFFFF;
173
}
174

    
175

    
176
// Plain old data class.  Represents a block of allocated memory.
177
class Block {
178
 public:
179
  Block(Address base_arg, int size_arg)
180
      : base(base_arg), size(size_arg) {}
181

    
182
  Address base;
183
  int size;
184
};
185

    
186

    
187
TEST(CodeRange) {
188
  const int code_range_size = 32*MB;
189
  CcTest::InitializeVM();
190
  CodeRange code_range(reinterpret_cast<Isolate*>(CcTest::isolate()));
191
  code_range.SetUp(code_range_size);
192
  int current_allocated = 0;
193
  int total_allocated = 0;
194
  List<Block> blocks(1000);
195

    
196
  while (total_allocated < 5 * code_range_size) {
197
    if (current_allocated < code_range_size / 10) {
198
      // Allocate a block.
199
      // Geometrically distributed sizes, greater than
200
      // Page::kMaxNonCodeHeapObjectSize (which is greater than code page area).
201
      // TODO(gc): instead of using 3 use some contant based on code_range_size
202
      // kMaxHeapObjectSize.
203
      size_t requested =
204
          (Page::kMaxNonCodeHeapObjectSize << (Pseudorandom() % 3)) +
205
          Pseudorandom() % 5000 + 1;
206
      size_t allocated = 0;
207
      Address base = code_range.AllocateRawMemory(requested,
208
                                                  requested,
209
                                                  &allocated);
210
      CHECK(base != NULL);
211
      blocks.Add(Block(base, static_cast<int>(allocated)));
212
      current_allocated += static_cast<int>(allocated);
213
      total_allocated += static_cast<int>(allocated);
214
    } else {
215
      // Free a block.
216
      int index = Pseudorandom() % blocks.length();
217
      code_range.FreeRawMemory(blocks[index].base, blocks[index].size);
218
      current_allocated -= blocks[index].size;
219
      if (index < blocks.length() - 1) {
220
        blocks[index] = blocks.RemoveLast();
221
      } else {
222
        blocks.RemoveLast();
223
      }
224
    }
225
  }
226

    
227
  code_range.TearDown();
228
}