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