• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2007-2010 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 <signal.h>
29 
30 #include "sys/stat.h"
31 #include "v8.h"
32 
33 #include "debug.h"
34 #include "ic-inl.h"
35 #include "runtime.h"
36 #include "serialize.h"
37 #include "scopeinfo.h"
38 #include "snapshot.h"
39 #include "cctest.h"
40 #include "spaces.h"
41 #include "objects.h"
42 #include "natives.h"
43 #include "bootstrapper.h"
44 
45 using namespace v8::internal;
46 
47 static const unsigned kCounters = 256;
48 static int local_counters[kCounters];
49 static const char* local_counter_names[kCounters];
50 
51 
CounterHash(const char * s)52 static unsigned CounterHash(const char* s) {
53   unsigned hash = 0;
54   while (*++s) {
55     hash |= hash << 5;
56     hash += *s;
57   }
58   return hash;
59 }
60 
61 
62 // Callback receiver to track counters in test.
counter_function(const char * name)63 static int* counter_function(const char* name) {
64   unsigned hash = CounterHash(name) % kCounters;
65   unsigned original_hash = hash;
66   USE(original_hash);
67   while (true) {
68     if (local_counter_names[hash] == name) {
69       return &local_counters[hash];
70     }
71     if (local_counter_names[hash] == 0) {
72       local_counter_names[hash] = name;
73       return &local_counters[hash];
74     }
75     if (strcmp(local_counter_names[hash], name) == 0) {
76       return &local_counters[hash];
77     }
78     hash = (hash + 1) % kCounters;
79     ASSERT(hash != original_hash);  // Hash table has been filled up.
80   }
81 }
82 
83 
84 template <class T>
AddressOf(T id)85 static Address AddressOf(T id) {
86   return ExternalReference(id, i::Isolate::Current()).address();
87 }
88 
89 
90 template <class T>
Encode(const ExternalReferenceEncoder & encoder,T id)91 static uint32_t Encode(const ExternalReferenceEncoder& encoder, T id) {
92   return encoder.Encode(AddressOf(id));
93 }
94 
95 
make_code(TypeCode type,int id)96 static int make_code(TypeCode type, int id) {
97   return static_cast<uint32_t>(type) << kReferenceTypeShift | id;
98 }
99 
100 
TEST(ExternalReferenceEncoder)101 TEST(ExternalReferenceEncoder) {
102   Isolate* isolate = i::Isolate::Current();
103   isolate->stats_table()->SetCounterFunction(counter_function);
104   v8::V8::Initialize();
105 
106   ExternalReferenceEncoder encoder;
107   CHECK_EQ(make_code(BUILTIN, Builtins::kArrayCode),
108            Encode(encoder, Builtins::kArrayCode));
109   CHECK_EQ(make_code(v8::internal::RUNTIME_FUNCTION, Runtime::kAbort),
110            Encode(encoder, Runtime::kAbort));
111   CHECK_EQ(make_code(IC_UTILITY, IC::kLoadCallbackProperty),
112            Encode(encoder, IC_Utility(IC::kLoadCallbackProperty)));
113   ExternalReference keyed_load_function_prototype =
114       ExternalReference(isolate->counters()->keyed_load_function_prototype());
115   CHECK_EQ(make_code(STATS_COUNTER, Counters::k_keyed_load_function_prototype),
116            encoder.Encode(keyed_load_function_prototype.address()));
117   ExternalReference stack_limit_address =
118       ExternalReference::address_of_stack_limit(isolate);
119   CHECK_EQ(make_code(UNCLASSIFIED, 4),
120            encoder.Encode(stack_limit_address.address()));
121   ExternalReference real_stack_limit_address =
122       ExternalReference::address_of_real_stack_limit(isolate);
123   CHECK_EQ(make_code(UNCLASSIFIED, 5),
124            encoder.Encode(real_stack_limit_address.address()));
125 #ifdef ENABLE_DEBUGGER_SUPPORT
126   CHECK_EQ(make_code(UNCLASSIFIED, 16),
127            encoder.Encode(ExternalReference::debug_break(isolate).address()));
128 #endif  // ENABLE_DEBUGGER_SUPPORT
129   CHECK_EQ(make_code(UNCLASSIFIED, 10),
130            encoder.Encode(
131                ExternalReference::new_space_start(isolate).address()));
132   CHECK_EQ(make_code(UNCLASSIFIED, 3),
133            encoder.Encode(
134                ExternalReference::roots_array_start(isolate).address()));
135 }
136 
137 
TEST(ExternalReferenceDecoder)138 TEST(ExternalReferenceDecoder) {
139   Isolate* isolate = i::Isolate::Current();
140   isolate->stats_table()->SetCounterFunction(counter_function);
141   v8::V8::Initialize();
142 
143   ExternalReferenceDecoder decoder;
144   CHECK_EQ(AddressOf(Builtins::kArrayCode),
145            decoder.Decode(make_code(BUILTIN, Builtins::kArrayCode)));
146   CHECK_EQ(AddressOf(Runtime::kAbort),
147            decoder.Decode(make_code(v8::internal::RUNTIME_FUNCTION,
148                                     Runtime::kAbort)));
149   CHECK_EQ(AddressOf(IC_Utility(IC::kLoadCallbackProperty)),
150            decoder.Decode(make_code(IC_UTILITY, IC::kLoadCallbackProperty)));
151   ExternalReference keyed_load_function =
152       ExternalReference(isolate->counters()->keyed_load_function_prototype());
153   CHECK_EQ(keyed_load_function.address(),
154            decoder.Decode(
155                make_code(STATS_COUNTER,
156                          Counters::k_keyed_load_function_prototype)));
157   CHECK_EQ(ExternalReference::address_of_stack_limit(isolate).address(),
158            decoder.Decode(make_code(UNCLASSIFIED, 4)));
159   CHECK_EQ(ExternalReference::address_of_real_stack_limit(isolate).address(),
160            decoder.Decode(make_code(UNCLASSIFIED, 5)));
161 #ifdef ENABLE_DEBUGGER_SUPPORT
162   CHECK_EQ(ExternalReference::debug_break(isolate).address(),
163            decoder.Decode(make_code(UNCLASSIFIED, 16)));
164 #endif  // ENABLE_DEBUGGER_SUPPORT
165   CHECK_EQ(ExternalReference::new_space_start(isolate).address(),
166            decoder.Decode(make_code(UNCLASSIFIED, 10)));
167 }
168 
169 
170 class FileByteSink : public SnapshotByteSink {
171  public:
FileByteSink(const char * snapshot_file)172   explicit FileByteSink(const char* snapshot_file) {
173     fp_ = OS::FOpen(snapshot_file, "wb");
174     file_name_ = snapshot_file;
175     if (fp_ == NULL) {
176       PrintF("Unable to write to snapshot file \"%s\"\n", snapshot_file);
177       exit(1);
178     }
179   }
~FileByteSink()180   virtual ~FileByteSink() {
181     if (fp_ != NULL) {
182       fclose(fp_);
183     }
184   }
Put(int byte,const char * description)185   virtual void Put(int byte, const char* description) {
186     if (fp_ != NULL) {
187       fputc(byte, fp_);
188     }
189   }
Position()190   virtual int Position() {
191     return ftell(fp_);
192   }
193   void WriteSpaceUsed(
194       int new_space_used,
195       int pointer_space_used,
196       int data_space_used,
197       int code_space_used,
198       int map_space_used,
199       int cell_space_used,
200       int large_space_used);
201 
202  private:
203   FILE* fp_;
204   const char* file_name_;
205 };
206 
207 
WriteSpaceUsed(int new_space_used,int pointer_space_used,int data_space_used,int code_space_used,int map_space_used,int cell_space_used,int large_space_used)208 void FileByteSink::WriteSpaceUsed(
209       int new_space_used,
210       int pointer_space_used,
211       int data_space_used,
212       int code_space_used,
213       int map_space_used,
214       int cell_space_used,
215       int large_space_used) {
216   int file_name_length = StrLength(file_name_) + 10;
217   Vector<char> name = Vector<char>::New(file_name_length + 1);
218   OS::SNPrintF(name, "%s.size", file_name_);
219   FILE* fp = OS::FOpen(name.start(), "w");
220   name.Dispose();
221   fprintf(fp, "new %d\n", new_space_used);
222   fprintf(fp, "pointer %d\n", pointer_space_used);
223   fprintf(fp, "data %d\n", data_space_used);
224   fprintf(fp, "code %d\n", code_space_used);
225   fprintf(fp, "map %d\n", map_space_used);
226   fprintf(fp, "cell %d\n", cell_space_used);
227   fprintf(fp, "large %d\n", large_space_used);
228   fclose(fp);
229 }
230 
231 
WriteToFile(const char * snapshot_file)232 static bool WriteToFile(const char* snapshot_file) {
233   FileByteSink file(snapshot_file);
234   StartupSerializer ser(&file);
235   ser.Serialize();
236   return true;
237 }
238 
239 
Serialize()240 static void Serialize() {
241   // We have to create one context.  One reason for this is so that the builtins
242   // can be loaded from v8natives.js and their addresses can be processed.  This
243   // will clear the pending fixups array, which would otherwise contain GC roots
244   // that would confuse the serialization/deserialization process.
245   v8::Persistent<v8::Context> env = v8::Context::New();
246   env.Dispose();
247   WriteToFile(FLAG_testing_serialization_file);
248 }
249 
250 
251 // Test that the whole heap can be serialized.
TEST(Serialize)252 TEST(Serialize) {
253   Serializer::Enable();
254   v8::V8::Initialize();
255   Serialize();
256 }
257 
258 
259 // Test that heap serialization is non-destructive.
TEST(SerializeTwice)260 TEST(SerializeTwice) {
261   Serializer::Enable();
262   v8::V8::Initialize();
263   Serialize();
264   Serialize();
265 }
266 
267 
268 //----------------------------------------------------------------------------
269 // Tests that the heap can be deserialized.
270 
Deserialize()271 static void Deserialize() {
272   CHECK(Snapshot::Initialize(FLAG_testing_serialization_file));
273 }
274 
275 
SanityCheck()276 static void SanityCheck() {
277   v8::HandleScope scope;
278 #ifdef DEBUG
279   HEAP->Verify();
280 #endif
281   CHECK(Isolate::Current()->global()->IsJSObject());
282   CHECK(Isolate::Current()->global_context()->IsContext());
283   CHECK(HEAP->symbol_table()->IsSymbolTable());
284   CHECK(!FACTORY->LookupAsciiSymbol("Empty")->IsFailure());
285 }
286 
287 
DEPENDENT_TEST(Deserialize,Serialize)288 DEPENDENT_TEST(Deserialize, Serialize) {
289   // The serialize-deserialize tests only work if the VM is built without
290   // serialization.  That doesn't matter.  We don't need to be able to
291   // serialize a snapshot in a VM that is booted from a snapshot.
292   if (!Snapshot::IsEnabled()) {
293     v8::HandleScope scope;
294     Deserialize();
295 
296     v8::Persistent<v8::Context> env = v8::Context::New();
297     env->Enter();
298 
299     SanityCheck();
300   }
301 }
302 
303 
DEPENDENT_TEST(DeserializeFromSecondSerialization,SerializeTwice)304 DEPENDENT_TEST(DeserializeFromSecondSerialization, SerializeTwice) {
305   if (!Snapshot::IsEnabled()) {
306     v8::HandleScope scope;
307     Deserialize();
308 
309     v8::Persistent<v8::Context> env = v8::Context::New();
310     env->Enter();
311 
312     SanityCheck();
313   }
314 }
315 
316 
DEPENDENT_TEST(DeserializeAndRunScript2,Serialize)317 DEPENDENT_TEST(DeserializeAndRunScript2, Serialize) {
318   if (!Snapshot::IsEnabled()) {
319     v8::HandleScope scope;
320     Deserialize();
321 
322     v8::Persistent<v8::Context> env = v8::Context::New();
323     env->Enter();
324 
325     const char* c_source = "\"1234\".length";
326     v8::Local<v8::String> source = v8::String::New(c_source);
327     v8::Local<v8::Script> script = v8::Script::Compile(source);
328     CHECK_EQ(4, script->Run()->Int32Value());
329   }
330 }
331 
332 
DEPENDENT_TEST(DeserializeFromSecondSerializationAndRunScript2,SerializeTwice)333 DEPENDENT_TEST(DeserializeFromSecondSerializationAndRunScript2,
334                SerializeTwice) {
335   if (!Snapshot::IsEnabled()) {
336     v8::HandleScope scope;
337     Deserialize();
338 
339     v8::Persistent<v8::Context> env = v8::Context::New();
340     env->Enter();
341 
342     const char* c_source = "\"1234\".length";
343     v8::Local<v8::String> source = v8::String::New(c_source);
344     v8::Local<v8::Script> script = v8::Script::Compile(source);
345     CHECK_EQ(4, script->Run()->Int32Value());
346   }
347 }
348 
349 
TEST(PartialSerialization)350 TEST(PartialSerialization) {
351   Serializer::Enable();
352   v8::V8::Initialize();
353 
354   v8::Persistent<v8::Context> env = v8::Context::New();
355   ASSERT(!env.IsEmpty());
356   env->Enter();
357   // Make sure all builtin scripts are cached.
358   { HandleScope scope;
359     for (int i = 0; i < Natives::GetBuiltinsCount(); i++) {
360       Isolate::Current()->bootstrapper()->NativesSourceLookup(i);
361     }
362   }
363   HEAP->CollectAllGarbage(Heap::kNoGCFlags);
364   HEAP->CollectAllGarbage(Heap::kNoGCFlags);
365 
366   Object* raw_foo;
367   {
368     v8::HandleScope handle_scope;
369     v8::Local<v8::String> foo = v8::String::New("foo");
370     ASSERT(!foo.IsEmpty());
371     raw_foo = *(v8::Utils::OpenHandle(*foo));
372   }
373 
374   int file_name_length = StrLength(FLAG_testing_serialization_file) + 10;
375   Vector<char> startup_name = Vector<char>::New(file_name_length + 1);
376   OS::SNPrintF(startup_name, "%s.startup", FLAG_testing_serialization_file);
377 
378   env->Exit();
379   env.Dispose();
380 
381   FileByteSink startup_sink(startup_name.start());
382   startup_name.Dispose();
383   StartupSerializer startup_serializer(&startup_sink);
384   startup_serializer.SerializeStrongReferences();
385 
386   FileByteSink partial_sink(FLAG_testing_serialization_file);
387   PartialSerializer p_ser(&startup_serializer, &partial_sink);
388   p_ser.Serialize(&raw_foo);
389   startup_serializer.SerializeWeakReferences();
390   partial_sink.WriteSpaceUsed(p_ser.CurrentAllocationAddress(NEW_SPACE),
391                               p_ser.CurrentAllocationAddress(OLD_POINTER_SPACE),
392                               p_ser.CurrentAllocationAddress(OLD_DATA_SPACE),
393                               p_ser.CurrentAllocationAddress(CODE_SPACE),
394                               p_ser.CurrentAllocationAddress(MAP_SPACE),
395                               p_ser.CurrentAllocationAddress(CELL_SPACE),
396                               p_ser.CurrentAllocationAddress(LO_SPACE));
397 }
398 
399 
ReserveSpaceForPartialSnapshot(const char * file_name)400 static void ReserveSpaceForPartialSnapshot(const char* file_name) {
401   int file_name_length = StrLength(file_name) + 10;
402   Vector<char> name = Vector<char>::New(file_name_length + 1);
403   OS::SNPrintF(name, "%s.size", file_name);
404   FILE* fp = OS::FOpen(name.start(), "r");
405   name.Dispose();
406   int new_size, pointer_size, data_size, code_size, map_size, cell_size;
407   int large_size;
408 #ifdef _MSC_VER
409   // Avoid warning about unsafe fscanf from MSVC.
410   // Please note that this is only fine if %c and %s are not being used.
411 #define fscanf fscanf_s
412 #endif
413   CHECK_EQ(1, fscanf(fp, "new %d\n", &new_size));
414   CHECK_EQ(1, fscanf(fp, "pointer %d\n", &pointer_size));
415   CHECK_EQ(1, fscanf(fp, "data %d\n", &data_size));
416   CHECK_EQ(1, fscanf(fp, "code %d\n", &code_size));
417   CHECK_EQ(1, fscanf(fp, "map %d\n", &map_size));
418   CHECK_EQ(1, fscanf(fp, "cell %d\n", &cell_size));
419   CHECK_EQ(1, fscanf(fp, "large %d\n", &large_size));
420 #ifdef _MSC_VER
421 #undef fscanf
422 #endif
423   fclose(fp);
424   HEAP->ReserveSpace(new_size,
425                      pointer_size,
426                      data_size,
427                      code_size,
428                      map_size,
429                      cell_size,
430                      large_size);
431 }
432 
433 
DEPENDENT_TEST(PartialDeserialization,PartialSerialization)434 DEPENDENT_TEST(PartialDeserialization, PartialSerialization) {
435   if (!Snapshot::IsEnabled()) {
436     int file_name_length = StrLength(FLAG_testing_serialization_file) + 10;
437     Vector<char> startup_name = Vector<char>::New(file_name_length + 1);
438     OS::SNPrintF(startup_name, "%s.startup", FLAG_testing_serialization_file);
439 
440     CHECK(Snapshot::Initialize(startup_name.start()));
441     startup_name.Dispose();
442 
443     const char* file_name = FLAG_testing_serialization_file;
444     ReserveSpaceForPartialSnapshot(file_name);
445 
446     int snapshot_size = 0;
447     byte* snapshot = ReadBytes(file_name, &snapshot_size);
448 
449     Object* root;
450     {
451       SnapshotByteSource source(snapshot, snapshot_size);
452       Deserializer deserializer(&source);
453       deserializer.DeserializePartial(&root);
454       CHECK(root->IsString());
455     }
456     v8::HandleScope handle_scope;
457     Handle<Object> root_handle(root);
458 
459     ReserveSpaceForPartialSnapshot(file_name);
460 
461     Object* root2;
462     {
463       SnapshotByteSource source(snapshot, snapshot_size);
464       Deserializer deserializer(&source);
465       deserializer.DeserializePartial(&root2);
466       CHECK(root2->IsString());
467       CHECK(*root_handle == root2);
468     }
469   }
470 }
471 
472 
TEST(ContextSerialization)473 TEST(ContextSerialization) {
474   Serializer::Enable();
475   v8::V8::Initialize();
476 
477   v8::Persistent<v8::Context> env = v8::Context::New();
478   ASSERT(!env.IsEmpty());
479   env->Enter();
480   // Make sure all builtin scripts are cached.
481   { HandleScope scope;
482     for (int i = 0; i < Natives::GetBuiltinsCount(); i++) {
483       Isolate::Current()->bootstrapper()->NativesSourceLookup(i);
484     }
485   }
486   // If we don't do this then we end up with a stray root pointing at the
487   // context even after we have disposed of env.
488   HEAP->CollectAllGarbage(Heap::kNoGCFlags);
489 
490   int file_name_length = StrLength(FLAG_testing_serialization_file) + 10;
491   Vector<char> startup_name = Vector<char>::New(file_name_length + 1);
492   OS::SNPrintF(startup_name, "%s.startup", FLAG_testing_serialization_file);
493 
494   env->Exit();
495 
496   Object* raw_context = *(v8::Utils::OpenHandle(*env));
497 
498   env.Dispose();
499 
500   FileByteSink startup_sink(startup_name.start());
501   startup_name.Dispose();
502   StartupSerializer startup_serializer(&startup_sink);
503   startup_serializer.SerializeStrongReferences();
504 
505   FileByteSink partial_sink(FLAG_testing_serialization_file);
506   PartialSerializer p_ser(&startup_serializer, &partial_sink);
507   p_ser.Serialize(&raw_context);
508   startup_serializer.SerializeWeakReferences();
509   partial_sink.WriteSpaceUsed(p_ser.CurrentAllocationAddress(NEW_SPACE),
510                               p_ser.CurrentAllocationAddress(OLD_POINTER_SPACE),
511                               p_ser.CurrentAllocationAddress(OLD_DATA_SPACE),
512                               p_ser.CurrentAllocationAddress(CODE_SPACE),
513                               p_ser.CurrentAllocationAddress(MAP_SPACE),
514                               p_ser.CurrentAllocationAddress(CELL_SPACE),
515                               p_ser.CurrentAllocationAddress(LO_SPACE));
516 }
517 
518 
DEPENDENT_TEST(ContextDeserialization,ContextSerialization)519 DEPENDENT_TEST(ContextDeserialization, ContextSerialization) {
520   if (!Snapshot::IsEnabled()) {
521     int file_name_length = StrLength(FLAG_testing_serialization_file) + 10;
522     Vector<char> startup_name = Vector<char>::New(file_name_length + 1);
523     OS::SNPrintF(startup_name, "%s.startup", FLAG_testing_serialization_file);
524 
525     CHECK(Snapshot::Initialize(startup_name.start()));
526     startup_name.Dispose();
527 
528     const char* file_name = FLAG_testing_serialization_file;
529     ReserveSpaceForPartialSnapshot(file_name);
530 
531     int snapshot_size = 0;
532     byte* snapshot = ReadBytes(file_name, &snapshot_size);
533 
534     Object* root;
535     {
536       SnapshotByteSource source(snapshot, snapshot_size);
537       Deserializer deserializer(&source);
538       deserializer.DeserializePartial(&root);
539       CHECK(root->IsContext());
540     }
541     v8::HandleScope handle_scope;
542     Handle<Object> root_handle(root);
543 
544     ReserveSpaceForPartialSnapshot(file_name);
545 
546     Object* root2;
547     {
548       SnapshotByteSource source(snapshot, snapshot_size);
549       Deserializer deserializer(&source);
550       deserializer.DeserializePartial(&root2);
551       CHECK(root2->IsContext());
552       CHECK(*root_handle != root2);
553     }
554   }
555 }
556 
557 
TEST(LinearAllocation)558 TEST(LinearAllocation) {
559   v8::V8::Initialize();
560   int new_space_max = 512 * KB;
561   int paged_space_max = Page::kMaxNonCodeHeapObjectSize;
562   int code_space_max = HEAP->code_space()->AreaSize();
563 
564   for (int size = 1000; size < 5 * MB; size += size >> 1) {
565     size &= ~8;  // Round.
566     int new_space_size = (size < new_space_max) ? size : new_space_max;
567     int paged_space_size = (size < paged_space_max) ? size : paged_space_max;
568     HEAP->ReserveSpace(
569         new_space_size,
570         paged_space_size,  // Old pointer space.
571         paged_space_size,  // Old data space.
572         HEAP->code_space()->RoundSizeDownToObjectAlignment(code_space_max),
573         HEAP->map_space()->RoundSizeDownToObjectAlignment(paged_space_size),
574         HEAP->cell_space()->RoundSizeDownToObjectAlignment(paged_space_size),
575         size);             // Large object space.
576     LinearAllocationScope linear_allocation_scope;
577     const int kSmallFixedArrayLength = 4;
578     const int kSmallFixedArraySize =
579         FixedArray::kHeaderSize + kSmallFixedArrayLength * kPointerSize;
580     const int kSmallStringLength = 16;
581     const int kSmallStringSize =
582         (SeqAsciiString::kHeaderSize + kSmallStringLength +
583         kObjectAlignmentMask) & ~kObjectAlignmentMask;
584     const int kMapSize = Map::kSize;
585 
586     Object* new_last = NULL;
587     for (int i = 0;
588          i + kSmallFixedArraySize <= new_space_size;
589          i += kSmallFixedArraySize) {
590       Object* obj =
591           HEAP->AllocateFixedArray(kSmallFixedArrayLength)->ToObjectChecked();
592       if (new_last != NULL) {
593         CHECK(reinterpret_cast<char*>(obj) ==
594               reinterpret_cast<char*>(new_last) + kSmallFixedArraySize);
595       }
596       new_last = obj;
597     }
598 
599     Object* pointer_last = NULL;
600     for (int i = 0;
601          i + kSmallFixedArraySize <= paged_space_size;
602          i += kSmallFixedArraySize) {
603       Object* obj = HEAP->AllocateFixedArray(kSmallFixedArrayLength,
604                                              TENURED)->ToObjectChecked();
605       int old_page_fullness = i % Page::kPageSize;
606       int page_fullness = (i + kSmallFixedArraySize) % Page::kPageSize;
607       if (page_fullness < old_page_fullness ||
608           page_fullness > HEAP->old_pointer_space()->AreaSize()) {
609         i = RoundUp(i, Page::kPageSize);
610         pointer_last = NULL;
611       }
612       if (pointer_last != NULL) {
613         CHECK(reinterpret_cast<char*>(obj) ==
614               reinterpret_cast<char*>(pointer_last) + kSmallFixedArraySize);
615       }
616       pointer_last = obj;
617     }
618 
619     Object* data_last = NULL;
620     for (int i = 0;
621          i + kSmallStringSize <= paged_space_size;
622          i += kSmallStringSize) {
623       Object* obj = HEAP->AllocateRawAsciiString(kSmallStringLength,
624                                                  TENURED)->ToObjectChecked();
625       int old_page_fullness = i % Page::kPageSize;
626       int page_fullness = (i + kSmallStringSize) % Page::kPageSize;
627       if (page_fullness < old_page_fullness ||
628           page_fullness > HEAP->old_data_space()->AreaSize()) {
629         i = RoundUp(i, Page::kPageSize);
630         data_last = NULL;
631       }
632       if (data_last != NULL) {
633         CHECK(reinterpret_cast<char*>(obj) ==
634               reinterpret_cast<char*>(data_last) + kSmallStringSize);
635       }
636       data_last = obj;
637     }
638 
639     Object* map_last = NULL;
640     for (int i = 0; i + kMapSize <= paged_space_size; i += kMapSize) {
641       Object* obj = HEAP->AllocateMap(JS_OBJECT_TYPE,
642                                       42 * kPointerSize)->ToObjectChecked();
643       int old_page_fullness = i % Page::kPageSize;
644       int page_fullness = (i + kMapSize) % Page::kPageSize;
645       if (page_fullness < old_page_fullness ||
646           page_fullness > HEAP->map_space()->AreaSize()) {
647         i = RoundUp(i, Page::kPageSize);
648         map_last = NULL;
649       }
650       if (map_last != NULL) {
651         CHECK(reinterpret_cast<char*>(obj) ==
652               reinterpret_cast<char*>(map_last) + kMapSize);
653       }
654       map_last = obj;
655     }
656 
657     if (size > Page::kMaxNonCodeHeapObjectSize) {
658       // Support for reserving space in large object space is not there yet,
659       // but using an always-allocate scope is fine for now.
660       AlwaysAllocateScope always;
661       int large_object_array_length =
662           (size - FixedArray::kHeaderSize) / kPointerSize;
663       Object* obj = HEAP->AllocateFixedArray(large_object_array_length,
664                                              TENURED)->ToObjectChecked();
665       CHECK(!obj->IsFailure());
666     }
667   }
668 }
669 
670 
TEST(TestThatAlwaysSucceeds)671 TEST(TestThatAlwaysSucceeds) {
672 }
673 
674 
TEST(TestThatAlwaysFails)675 TEST(TestThatAlwaysFails) {
676   bool ArtificialFailure = false;
677   CHECK(ArtificialFailure);
678 }
679 
680 
DEPENDENT_TEST(DependentTestThatAlwaysFails,TestThatAlwaysSucceeds)681 DEPENDENT_TEST(DependentTestThatAlwaysFails, TestThatAlwaysSucceeds) {
682   bool ArtificialFailure2 = false;
683   CHECK(ArtificialFailure2);
684 }
685