v8  3.14.5(node0.10.28)
V8 is Google's open source JavaScript engine
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
test-alloc.cc
Go to the documentation of this file.
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 // Also used in test-heap.cc test cases.
39  int old_linear_size = static_cast<int>(space->limit() - space->top());
40  space->Free(space->top(), old_linear_size);
41  space->SetTop(space->limit(), space->limit());
42  space->ResetFreeList();
43  space->ClearStats();
44 }
45 
46 
47 static MaybeObject* AllocateAfterFailures() {
48  static int attempts = 0;
49  if (++attempts < 3) return Failure::RetryAfterGC();
50  Heap* heap = Isolate::Current()->heap();
51 
52  // New space.
53  NewSpace* new_space = heap->new_space();
54  static const int kNewSpaceFillerSize = ByteArray::SizeFor(0);
55  while (new_space->Available() > kNewSpaceFillerSize) {
56  int available_before = static_cast<int>(new_space->Available());
57  CHECK(!heap->AllocateByteArray(0)->IsFailure());
58  if (available_before == new_space->Available()) {
59  // It seems that we are avoiding new space allocations when
60  // allocation is forced, so no need to fill up new space
61  // in order to make the test harder.
62  break;
63  }
64  }
65  CHECK(!heap->AllocateByteArray(100)->IsFailure());
66  CHECK(!heap->AllocateFixedArray(100, NOT_TENURED)->IsFailure());
67 
68  // Make sure we can allocate through optimized allocation functions
69  // for specific kinds.
70  CHECK(!heap->AllocateFixedArray(100)->IsFailure());
71  CHECK(!heap->AllocateHeapNumber(0.42)->IsFailure());
72  CHECK(!heap->AllocateArgumentsObject(Smi::FromInt(87), 10)->IsFailure());
73  Object* object = heap->AllocateJSObject(
74  *Isolate::Current()->object_function())->ToObjectChecked();
75  CHECK(!heap->CopyJSObject(JSObject::cast(object))->IsFailure());
76 
77  // Old data space.
79  CHECK(!heap->AllocateRawAsciiString(100, TENURED)->IsFailure());
80 
81  // Old pointer space.
83  CHECK(!heap->AllocateFixedArray(10000, TENURED)->IsFailure());
84 
85  // Large object space.
86  static const int kLargeObjectSpaceFillerLength = 300000;
87  static const int kLargeObjectSpaceFillerSize = FixedArray::SizeFor(
88  kLargeObjectSpaceFillerLength);
89  ASSERT(kLargeObjectSpaceFillerSize > heap->old_pointer_space()->AreaSize());
90  while (heap->OldGenerationSpaceAvailable() > kLargeObjectSpaceFillerSize) {
91  CHECK(!heap->AllocateFixedArray(kLargeObjectSpaceFillerLength, TENURED)->
92  IsFailure());
93  }
94  CHECK(!heap->AllocateFixedArray(kLargeObjectSpaceFillerLength, TENURED)->
95  IsFailure());
96 
97  // Map space.
99  int instance_size = JSObject::kHeaderSize;
100  CHECK(!heap->AllocateMap(JS_OBJECT_TYPE, instance_size)->IsFailure());
101 
102  // Test that we can allocate in old pointer space and code space.
103  CHECK(!heap->AllocateFixedArray(100, TENURED)->IsFailure());
104  CHECK(!heap->CopyCode(Isolate::Current()->builtins()->builtin(
105  Builtins::kIllegal))->IsFailure());
106 
107  // Return success.
108  return Smi::FromInt(42);
109 }
110 
111 
112 static Handle<Object> Test() {
113  CALL_HEAP_FUNCTION(ISOLATE, AllocateAfterFailures(), Object);
114 }
115 
116 
117 TEST(StressHandles) {
119  v8::HandleScope scope;
120  env->Enter();
121  Handle<Object> o = Test();
122  CHECK(o->IsSmi() && Smi::cast(*o)->value() == 42);
123  env->Exit();
124 }
125 
126 
127 static MaybeObject* TestAccessorGet(Object* object, void*) {
128  return AllocateAfterFailures();
129 }
130 
131 
133  TestAccessorGet,
134  0,
135  0
136 };
137 
138 
139 TEST(StressJS) {
141  v8::HandleScope scope;
142  env->Enter();
143  Handle<JSFunction> function =
144  FACTORY->NewFunction(FACTORY->function_symbol(), FACTORY->null_value());
145  // Force the creation of an initial map and set the code to
146  // something empty.
147  FACTORY->NewJSObject(function);
148  function->ReplaceCode(Isolate::Current()->builtins()->builtin(
149  Builtins::kEmptyFunction));
150  // Patch the map to have an accessor for "get".
151  Handle<Map> map(function->initial_map());
152  Handle<DescriptorArray> instance_descriptors(map->instance_descriptors());
153  Handle<Foreign> foreign = FACTORY->NewForeign(&kDescriptor);
154  Handle<String> name =
155  FACTORY->NewStringFromAscii(Vector<const char>("get", 3));
156  ASSERT(instance_descriptors->IsEmpty());
157 
158  Handle<DescriptorArray> new_descriptors = FACTORY->NewDescriptorArray(0, 1);
159 
160  v8::internal::DescriptorArray::WhitenessWitness witness(*new_descriptors);
161  map->set_instance_descriptors(*new_descriptors);
162 
163  CallbacksDescriptor d(*name,
164  *foreign,
165  static_cast<PropertyAttributes>(0),
166  v8::internal::PropertyDetails::kInitialIndex);
167  map->AppendDescriptor(&d, witness);
168 
169  // Add the Foo constructor the global object.
170  env->Global()->Set(v8::String::New("Foo"), v8::Utils::ToLocal(function));
171  // Call the accessor through JavaScript.
172  v8::Handle<v8::Value> result =
173  v8::Script::Compile(v8::String::New("(new Foo).get"))->Run();
174  CHECK_EQ(42, result->Int32Value());
175  env->Exit();
176 }
177 
178 
179 // CodeRange test.
180 // Tests memory management in a CodeRange by allocating and freeing blocks,
181 // using a pseudorandom generator to choose block sizes geometrically
182 // distributed between 2 * Page::kPageSize and 2^5 + 1 * Page::kPageSize.
183 // Ensure that the freed chunks are collected and reused by allocating (in
184 // total) more than the size of the CodeRange.
185 
186 // This pseudorandom generator does not need to be particularly good.
187 // Use the lower half of the V8::Random() generator.
188 unsigned int Pseudorandom() {
189  static uint32_t lo = 2345;
190  lo = 18273 * (lo & 0xFFFF) + (lo >> 16); // Provably not 0.
191  return lo & 0xFFFF;
192 }
193 
194 
195 // Plain old data class. Represents a block of allocated memory.
196 class Block {
197  public:
198  Block(Address base_arg, int size_arg)
199  : base(base_arg), size(size_arg) {}
200 
202  int size;
203 };
204 
205 
207  const int code_range_size = 32*MB;
208  OS::SetUp();
209  Isolate::Current()->InitializeLoggingAndCounters();
210  CodeRange* code_range = new CodeRange(Isolate::Current());
211  code_range->SetUp(code_range_size);
212  int current_allocated = 0;
213  int total_allocated = 0;
214  List<Block> blocks(1000);
215 
216  while (total_allocated < 5 * code_range_size) {
217  if (current_allocated < code_range_size / 10) {
218  // Allocate a block.
219  // Geometrically distributed sizes, greater than
220  // Page::kMaxNonCodeHeapObjectSize (which is greater than code page area).
221  // TODO(gc): instead of using 3 use some contant based on code_range_size
222  // kMaxHeapObjectSize.
223  size_t requested =
225  Pseudorandom() % 5000 + 1;
226  size_t allocated = 0;
227  Address base = code_range->AllocateRawMemory(requested, &allocated);
228  CHECK(base != NULL);
229  blocks.Add(Block(base, static_cast<int>(allocated)));
230  current_allocated += static_cast<int>(allocated);
231  total_allocated += static_cast<int>(allocated);
232  } else {
233  // Free a block.
234  int index = Pseudorandom() % blocks.length();
235  code_range->FreeRawMemory(blocks[index].base, blocks[index].size);
236  current_allocated -= blocks[index].size;
237  if (index < blocks.length() - 1) {
238  blocks[index] = blocks.RemoveLast();
239  } else {
240  blocks.RemoveLast();
241  }
242  }
243  }
244 
245  code_range->TearDown();
246  delete code_range;
247 }
byte * Address
Definition: globals.h:157
MUST_USE_RESULT MaybeObject * CopyCode(Code *code)
Definition: heap.cc:3667
static Local< Script > Compile(Handle< String > source, ScriptOrigin *origin=NULL, ScriptData *pre_data=NULL, Handle< String > script_data=Handle< String >())
Definition: api.cc:1568
#define CHECK_EQ(expected, value)
Definition: checks.h:219
MUST_USE_RESULT MaybeObject * AllocateFixedArray(int length, PretenureFlag pretenure)
Definition: heap.cc:4819
void SetTop(Address top, Address limit)
Definition: spaces.h:1550
bool SetUp(const size_t requested_size)
Definition: spaces.cc:135
static Smi * FromInt(int value)
Definition: objects-inl.h:981
MUST_USE_RESULT MaybeObject * AllocateJSObject(JSFunction *constructor, PretenureFlag pretenure=NOT_TENURED)
Definition: heap.cc:4041
static V8EXPORT Local< String > New(const char *data, int length=-1)
Definition: api.cc:4779
MUST_USE_RESULT MaybeObject * AllocateByteArray(int length, PretenureFlag pretenure)
Definition: heap.cc:3517
Address base
Definition: test-alloc.cc:201
MUST_USE_RESULT MaybeObject * AllocateRawAsciiString(int length, PretenureFlag pretenure=NOT_TENURED)
Definition: heap.cc:4579
#define ASSERT(condition)
Definition: checks.h:270
#define CHECK(condition)
Definition: checks.h:56
MUST_USE_RESULT MaybeObject * CopyJSObject(JSObject *source)
Definition: heap.cc:4254
MUST_USE_RESULT MaybeObject * AllocateHeapNumber(double value, PretenureFlag pretenure)
Definition: heap.cc:2483
static Smi * cast(Object *object)
unsigned int Pseudorandom()
Definition: test-alloc.cc:188
static Failure * RetryAfterGC()
Definition: objects-inl.h:1040
#define CALL_HEAP_FUNCTION(ISOLATE, FUNCTION_CALL, TYPE)
Definition: heap-inl.h:558
V8EXPORT int32_t Int32Value() const
Definition: api.cc:2662
intptr_t Available()
Definition: spaces.h:2162
OldSpace * old_pointer_space()
Definition: heap.h:506
static const int kMaxNonCodeHeapObjectSize
Definition: spaces.h:717
MUST_USE_RESULT Address AllocateRawMemory(const size_t requested, size_t *allocated)
Definition: spaces.cc:211
void SimulateFullSpace(PagedSpace *space)
Definition: test-alloc.cc:38
int Free(Address start, int size_in_bytes)
Definition: spaces.h:1539
static Local< Context > ToLocal(v8::internal::Handle< v8::internal::Context > obj)
static int SizeFor(int length)
Definition: objects.h:2353
#define ISOLATE
Definition: isolate.h:1435
int size
Definition: test-alloc.cc:202
static int SizeFor(int length)
Definition: objects.h:3635
MUST_USE_RESULT MaybeObject * AllocateArgumentsObject(Object *callee, int length)
Definition: heap.cc:3827
Block(Address base_arg, int size_arg)
Definition: test-alloc.cc:198
static void SetUp()
static const int kHeaderSize
Definition: objects.h:2173
MapSpace * map_space()
Definition: heap.h:509
void Add(const T &element, AllocationPolicy allocator=AllocationPolicy())
Definition: list-inl.h:38
#define FACTORY
Definition: isolate.h:1434
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 and VFP2 enable use of VFP2 instructions if available enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of MIPS FPU instructions if NULL
Definition: flags.cc:301
const AccessorDescriptor kDescriptor
Definition: test-alloc.cc:132
static Persistent< Context > New(ExtensionConfiguration *extensions=NULL, Handle< ObjectTemplate > global_template=Handle< ObjectTemplate >(), Handle< Value > global_object=Handle< Value >())
Definition: api.cc:4411
void FreeRawMemory(Address buf, size_t length)
Definition: spaces.cc:245
intptr_t OldGenerationSpaceAvailable()
Definition: heap.h:1390
NewSpace * new_space()
Definition: heap.h:505
MUST_USE_RESULT MaybeObject * AllocateMap(InstanceType instance_type, int instance_size, ElementsKind elements_kind=TERMINAL_FAST_ELEMENTS_KIND)
Definition: heap.cc:2085
static JSObject * cast(Object *obj)
OldSpace * old_data_space()
Definition: heap.h:507
const int MB
Definition: globals.h:208