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 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 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: 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 } 185 virtual ~FileByteSink() { 186 if (fp_ != NULL) { 187 fclose(fp_); 188 } 189 } 190 virtual void Put(int byte, const char* description) { 191 if (fp_ != NULL) { 192 fputc(byte, fp_); 193 } 194 } 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 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 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 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. 257 TEST(Serialize) { 258 Serializer::Enable(); 259 v8::V8::Initialize(); 260 Serialize(); 261 } 262 263 264 // Test that heap serialization is non-destructive. 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 276 static void Deserialize() { 277 CHECK(Snapshot::Initialize(FLAG_testing_serialization_file)); 278 } 279 280 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 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 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 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 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 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 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 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 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 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 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 666 TEST(TestThatAlwaysSucceeds) { 667 } 668 669 670 TEST(TestThatAlwaysFails) { 671 bool ArtificialFailure = false; 672 CHECK(ArtificialFailure); 673 } 674 675 676 DEPENDENT_TEST(DependentTestThatAlwaysFails, TestThatAlwaysSucceeds) { 677 bool ArtificialFailure2 = false; 678 CHECK(ArtificialFailure2); 679 } 680