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