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 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. 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> 85 static Address AddressOf(T id) { 86 return ExternalReference(id, i::Isolate::Current()).address(); 87 } 88 89 90 template <class T> 91 static uint32_t Encode(const ExternalReferenceEncoder& encoder, T id) { 92 return encoder.Encode(AddressOf(id)); 93 } 94 95 96 static int make_code(TypeCode type, int id) { 97 return static_cast<uint32_t>(type) << kReferenceTypeShift | id; 98 } 99 100 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 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: 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 } 180 virtual ~FileByteSink() { 181 if (fp_ != NULL) { 182 fclose(fp_); 183 } 184 } 185 virtual void Put(int byte, const char* description) { 186 if (fp_ != NULL) { 187 fputc(byte, fp_); 188 } 189 } 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 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 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 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. 252 TEST(Serialize) { 253 Serializer::Enable(); 254 v8::V8::Initialize(); 255 Serialize(); 256 } 257 258 259 // Test that heap serialization is non-destructive. 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 271 static void Deserialize() { 272 CHECK(Snapshot::Initialize(FLAG_testing_serialization_file)); 273 } 274 275 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 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 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 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 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 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 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 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 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 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 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 671 TEST(TestThatAlwaysSucceeds) { 672 } 673 674 675 TEST(TestThatAlwaysFails) { 676 bool ArtificialFailure = false; 677 CHECK(ArtificialFailure); 678 } 679 680 681 DEPENDENT_TEST(DependentTestThatAlwaysFails, TestThatAlwaysSucceeds) { 682 bool ArtificialFailure2 = false; 683 CHECK(ArtificialFailure2); 684 } 685