00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "v8.h"
00029
00030 #include "accessors.h"
00031 #include "api.h"
00032 #include "execution.h"
00033 #include "global-handles.h"
00034 #include "ic-inl.h"
00035 #include "natives.h"
00036 #include "platform.h"
00037 #include "runtime.h"
00038 #include "serialize.h"
00039 #include "stub-cache.h"
00040 #include "v8threads.h"
00041
00042 namespace v8 { namespace internal {
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053 const int kSpaceShift = kHeapObjectTagSize;
00054 const int kSpaceBits = kSpaceTagSize;
00055 const int kSpaceMask = kSpaceTagMask;
00056
00057
00058
00059
00060
00061 const int kLOSpaceExecutable = LAST_SPACE + 1;
00062
00063
00064 const int kLOSpacePointer = LAST_SPACE + 2;
00065
00066
00067 const int kOffsetShift = kSpaceShift + kSpaceBits;
00068 const int kOffsetBits = 11;
00069 const int kOffsetMask = (1 << kOffsetBits) - 1;
00070
00071 const int kPageBits = 32 - (kOffsetBits + kSpaceBits + kHeapObjectTagSize);
00072 const int kPageShift = kOffsetShift + kOffsetBits;
00073 const int kPageMask = (1 << kPageBits) - 1;
00074
00075 const int kPageAndOffsetShift = kOffsetShift;
00076 const int kPageAndOffsetBits = kPageBits + kOffsetBits;
00077 const int kPageAndOffsetMask = (1 << kPageAndOffsetBits) - 1;
00078
00079
00080 static inline AllocationSpace GetSpace(Address addr) {
00081 const int encoded = reinterpret_cast<int>(addr);
00082 int space_number = ((encoded >> kSpaceShift) & kSpaceMask);
00083 if (space_number == kLOSpaceExecutable) space_number = LO_SPACE;
00084 else if (space_number == kLOSpacePointer) space_number = LO_SPACE;
00085 return static_cast<AllocationSpace>(space_number);
00086 }
00087
00088
00089 static inline bool IsLargeExecutableObject(Address addr) {
00090 const int encoded = reinterpret_cast<int>(addr);
00091 const int space_number = ((encoded >> kSpaceShift) & kSpaceMask);
00092 if (space_number == kLOSpaceExecutable) return true;
00093 return false;
00094 }
00095
00096
00097 static inline bool IsLargeFixedArray(Address addr) {
00098 const int encoded = reinterpret_cast<int>(addr);
00099 const int space_number = ((encoded >> kSpaceShift) & kSpaceMask);
00100 if (space_number == kLOSpacePointer) return true;
00101 return false;
00102 }
00103
00104
00105 static inline int PageIndex(Address addr) {
00106 const int encoded = reinterpret_cast<int>(addr);
00107 return (encoded >> kPageShift) & kPageMask;
00108 }
00109
00110
00111 static inline int PageOffset(Address addr) {
00112 const int encoded = reinterpret_cast<int>(addr);
00113 return ((encoded >> kOffsetShift) & kOffsetMask) << kObjectAlignmentBits;
00114 }
00115
00116
00117 static inline int NewSpaceOffset(Address addr) {
00118 const int encoded = reinterpret_cast<int>(addr);
00119 return ((encoded >> kPageAndOffsetShift) & kPageAndOffsetMask) <<
00120 kObjectAlignmentBits;
00121 }
00122
00123
00124 static inline int LargeObjectIndex(Address addr) {
00125 const int encoded = reinterpret_cast<int>(addr);
00126 return (encoded >> kPageAndOffsetShift) & kPageAndOffsetMask;
00127 }
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141 class RelativeAddress {
00142 public:
00143 RelativeAddress(AllocationSpace space,
00144 int page_index,
00145 int page_offset)
00146 : space_(space), page_index_(page_index), page_offset_(page_offset) {
00147 ASSERT(space <= LAST_SPACE && space >= 0);
00148 }
00149
00150
00151 Address Encode() const;
00152
00153 AllocationSpace space() const {
00154 if (space_ == kLOSpaceExecutable) return LO_SPACE;
00155 if (space_ == kLOSpacePointer) return LO_SPACE;
00156 return static_cast<AllocationSpace>(space_);
00157 }
00158 int page_index() const { return page_index_; }
00159 int page_offset() const { return page_offset_; }
00160
00161 bool in_paged_space() const {
00162 return space_ == CODE_SPACE ||
00163 space_ == OLD_POINTER_SPACE ||
00164 space_ == OLD_DATA_SPACE ||
00165 space_ == MAP_SPACE;
00166 }
00167
00168 void next_address(int offset) { page_offset_ += offset; }
00169 void next_page(int init_offset = 0) {
00170 page_index_++;
00171 page_offset_ = init_offset;
00172 }
00173
00174 #ifdef DEBUG
00175 void Verify();
00176 #endif
00177
00178 void set_to_large_code_object() {
00179 ASSERT(space_ == LO_SPACE);
00180 space_ = kLOSpaceExecutable;
00181 }
00182 void set_to_large_fixed_array() {
00183 ASSERT(space_ == LO_SPACE);
00184 space_ = kLOSpacePointer;
00185 }
00186
00187
00188 private:
00189 int space_;
00190 int page_index_;
00191 int page_offset_;
00192 };
00193
00194
00195 Address RelativeAddress::Encode() const {
00196 ASSERT(page_index_ >= 0);
00197 int word_offset = 0;
00198 int result = 0;
00199 switch (space_) {
00200 case MAP_SPACE:
00201 case OLD_POINTER_SPACE:
00202 case OLD_DATA_SPACE:
00203 case CODE_SPACE:
00204 ASSERT_EQ(0, page_index_ & ~kPageMask);
00205 word_offset = page_offset_ >> kObjectAlignmentBits;
00206 ASSERT_EQ(0, word_offset & ~kOffsetMask);
00207 result = (page_index_ << kPageShift) | (word_offset << kOffsetShift);
00208 break;
00209 case NEW_SPACE:
00210 ASSERT_EQ(0, page_index_);
00211 word_offset = page_offset_ >> kObjectAlignmentBits;
00212 ASSERT_EQ(0, word_offset & ~kPageAndOffsetMask);
00213 result = word_offset << kPageAndOffsetShift;
00214 break;
00215 case LO_SPACE:
00216 case kLOSpaceExecutable:
00217 case kLOSpacePointer:
00218 ASSERT_EQ(0, page_offset_);
00219 ASSERT_EQ(0, page_index_ & ~kPageAndOffsetMask);
00220 result = page_index_ << kPageAndOffsetShift;
00221 break;
00222 }
00223
00224 ASSERT_EQ(0, space_ & ~kSpaceMask);
00225 result |= (space_ << kSpaceShift) | kHeapObjectTag;
00226 return reinterpret_cast<Address>(result);
00227 }
00228
00229
00230 #ifdef DEBUG
00231 void RelativeAddress::Verify() {
00232 ASSERT(page_offset_ >= 0 && page_index_ >= 0);
00233 switch (space_) {
00234 case MAP_SPACE:
00235 case OLD_POINTER_SPACE:
00236 case OLD_DATA_SPACE:
00237 case CODE_SPACE:
00238 ASSERT(Page::kObjectStartOffset <= page_offset_ &&
00239 page_offset_ <= Page::kPageSize);
00240 break;
00241 case NEW_SPACE:
00242 ASSERT(page_index_ == 0);
00243 break;
00244 case LO_SPACE:
00245 case kLOSpaceExecutable:
00246 case kLOSpacePointer:
00247 ASSERT(page_offset_ == 0);
00248 break;
00249 }
00250 }
00251 #endif
00252
00253 enum GCTreatment {
00254 DataObject,
00255 PointerObject,
00256 CodeObject
00257 };
00258
00259
00260
00261
00262
00263
00264 class SimulatedHeapSpace {
00265 public:
00266
00267 SimulatedHeapSpace(): current_(LAST_SPACE, -1, -1) {}
00268
00269
00270
00271 void InitEmptyHeap(AllocationSpace space);
00272
00273
00274
00275
00276 void InitCurrentHeap(AllocationSpace space);
00277
00278
00279
00280
00281 RelativeAddress Allocate(int size, GCTreatment special_gc_treatment);
00282
00283 private:
00284 RelativeAddress current_;
00285 };
00286
00287
00288 void SimulatedHeapSpace::InitEmptyHeap(AllocationSpace space) {
00289 switch (space) {
00290 case MAP_SPACE:
00291 case OLD_POINTER_SPACE:
00292 case OLD_DATA_SPACE:
00293 case CODE_SPACE:
00294 current_ = RelativeAddress(space, 0, Page::kObjectStartOffset);
00295 break;
00296 case NEW_SPACE:
00297 case LO_SPACE:
00298 current_ = RelativeAddress(space, 0, 0);
00299 break;
00300 }
00301 }
00302
00303
00304 void SimulatedHeapSpace::InitCurrentHeap(AllocationSpace space) {
00305 switch (space) {
00306 case MAP_SPACE:
00307 case OLD_POINTER_SPACE:
00308 case OLD_DATA_SPACE:
00309 case CODE_SPACE: {
00310 PagedSpace* ps;
00311 if (space == MAP_SPACE) {
00312 ps = Heap::map_space();
00313 } else if (space == OLD_POINTER_SPACE) {
00314 ps = Heap::old_pointer_space();
00315 } else if (space == OLD_DATA_SPACE) {
00316 ps = Heap::old_data_space();
00317 } else {
00318 ASSERT(space == CODE_SPACE);
00319 ps = Heap::code_space();
00320 }
00321 Address top = ps->top();
00322 Page* top_page = Page::FromAllocationTop(top);
00323 int page_index = 0;
00324 PageIterator it(ps, PageIterator::PAGES_IN_USE);
00325 while (it.has_next()) {
00326 if (it.next() == top_page) break;
00327 page_index++;
00328 }
00329 current_ = RelativeAddress(space,
00330 page_index,
00331 top_page->Offset(top));
00332 break;
00333 }
00334 case NEW_SPACE:
00335 current_ = RelativeAddress(space,
00336 0,
00337 Heap::NewSpaceTop() - Heap::NewSpaceStart());
00338 break;
00339 case LO_SPACE:
00340 int page_index = 0;
00341 for (LargeObjectIterator it(Heap::lo_space()); it.has_next(); it.next()) {
00342 page_index++;
00343 }
00344 current_ = RelativeAddress(space, page_index, 0);
00345 break;
00346 }
00347 }
00348
00349
00350 RelativeAddress SimulatedHeapSpace::Allocate(int size,
00351 GCTreatment special_gc_treatment) {
00352 #ifdef DEBUG
00353 current_.Verify();
00354 #endif
00355 int alloc_size = OBJECT_SIZE_ALIGN(size);
00356 if (current_.in_paged_space() &&
00357 current_.page_offset() + alloc_size > Page::kPageSize) {
00358 ASSERT(alloc_size <= Page::kMaxHeapObjectSize);
00359 current_.next_page(Page::kObjectStartOffset);
00360 }
00361 RelativeAddress result = current_;
00362 if (current_.space() == LO_SPACE) {
00363 current_.next_page();
00364 if (special_gc_treatment == CodeObject) {
00365 result.set_to_large_code_object();
00366 } else if (special_gc_treatment == PointerObject) {
00367 result.set_to_large_fixed_array();
00368 }
00369 } else {
00370 current_.next_address(alloc_size);
00371 }
00372 #ifdef DEBUG
00373 current_.Verify();
00374 result.Verify();
00375 #endif
00376 return result;
00377 }
00378
00379
00380
00381
00382
00383
00384 static uint32_t EncodeExternal(TypeCode type, uint16_t id) {
00385 return static_cast<uint32_t>(type) << 16 | id;
00386 }
00387
00388
00389 static int* GetInternalPointer(StatsCounter* counter) {
00390
00391
00392 static int dummy_counter = 0;
00393 return counter->Enabled() ? counter->GetInternalPointer() : &dummy_counter;
00394 }
00395
00396
00397
00398
00399
00400 class ExternalReferenceTable {
00401 public:
00402 static ExternalReferenceTable* instance() {
00403 if (!instance_) instance_ = new ExternalReferenceTable();
00404 return instance_;
00405 }
00406
00407 int size() const { return refs_.length(); }
00408
00409 Address address(int i) { return refs_[i].address; }
00410
00411 uint32_t code(int i) { return refs_[i].code; }
00412
00413 const char* name(int i) { return refs_[i].name; }
00414
00415 int max_id(int code) { return max_id_[code]; }
00416
00417 private:
00418 static ExternalReferenceTable* instance_;
00419
00420 ExternalReferenceTable();
00421
00422 struct ExternalReferenceEntry {
00423 Address address;
00424 uint32_t code;
00425 const char* name;
00426 };
00427
00428 void Add(Address address, TypeCode type, uint16_t id, const char* name) {
00429 CHECK_NE(NULL, address);
00430 ExternalReferenceEntry entry;
00431 entry.address = address;
00432 entry.code = EncodeExternal(type, id);
00433 entry.name = name;
00434 CHECK_NE(0, entry.code);
00435 refs_.Add(entry);
00436 if (id > max_id_[type]) max_id_[type] = id;
00437 }
00438
00439 List<ExternalReferenceEntry> refs_;
00440 int max_id_[kTypeCodeCount];
00441 };
00442
00443
00444 ExternalReferenceTable* ExternalReferenceTable::instance_ = NULL;
00445
00446
00447 ExternalReferenceTable::ExternalReferenceTable() : refs_(64) {
00448 for (int type_code = 0; type_code < kTypeCodeCount; type_code++) {
00449 max_id_[type_code] = 0;
00450 }
00451
00452
00453
00454
00455 #define DEF_ENTRY_C(name) \
00456 Add(Builtins::c_function_address(Builtins::c_##name), \
00457 C_BUILTIN, \
00458 Builtins::c_##name, \
00459 "Builtins::" #name);
00460
00461 BUILTIN_LIST_C(DEF_ENTRY_C)
00462 #undef DEF_ENTRY_C
00463
00464 #define DEF_ENTRY_C(name) \
00465 Add(Builtins::builtin_address(Builtins::name), \
00466 BUILTIN, \
00467 Builtins::name, \
00468 "Builtins::" #name);
00469 #define DEF_ENTRY_A(name, kind, state) DEF_ENTRY_C(name)
00470
00471 BUILTIN_LIST_C(DEF_ENTRY_C)
00472 BUILTIN_LIST_A(DEF_ENTRY_A)
00473 #undef DEF_ENTRY_C
00474 #undef DEF_ENTRY_A
00475
00476
00477 #define RUNTIME_ENTRY(name, nargs) \
00478 Add(Runtime::FunctionForId(Runtime::k##name)->entry, \
00479 RUNTIME_FUNCTION, \
00480 Runtime::k##name, \
00481 "Runtime::" #name);
00482
00483 RUNTIME_FUNCTION_LIST(RUNTIME_ENTRY)
00484 #undef RUNTIME_ENTRY
00485
00486
00487 #define IC_ENTRY(name) \
00488 Add(IC::AddressFromUtilityId(IC::k##name), \
00489 IC_UTILITY, \
00490 IC::k##name, \
00491 "IC::" #name);
00492
00493 IC_UTIL_LIST(IC_ENTRY)
00494 #undef IC_ENTRY
00495
00496
00497 Add(Debug_Address(Debug::k_after_break_target_address).address(),
00498 DEBUG_ADDRESS,
00499 Debug::k_after_break_target_address << kDebugIdShift,
00500 "Debug::after_break_target_address()");
00501 Add(Debug_Address(Debug::k_debug_break_return_address).address(),
00502 DEBUG_ADDRESS,
00503 Debug::k_debug_break_return_address << kDebugIdShift,
00504 "Debug::debug_break_return_address()");
00505 const char* debug_register_format = "Debug::register_address(%i)";
00506 size_t dr_format_length = strlen(debug_register_format);
00507 for (int i = 0; i < kNumJSCallerSaved; ++i) {
00508 Vector<char> name = Vector<char>::New(dr_format_length + 1);
00509 OS::SNPrintF(name, debug_register_format, i);
00510 Add(Debug_Address(Debug::k_register_address, i).address(),
00511 DEBUG_ADDRESS,
00512 Debug::k_register_address << kDebugIdShift | i,
00513 name.start());
00514 }
00515
00516
00517 #define COUNTER_ENTRY(name, caption) \
00518 Add(reinterpret_cast<Address>(GetInternalPointer(&Counters::name)), \
00519 STATS_COUNTER, \
00520 Counters::k_##name, \
00521 "Counters::" #name);
00522
00523 STATS_COUNTER_LIST_1(COUNTER_ENTRY)
00524 STATS_COUNTER_LIST_2(COUNTER_ENTRY)
00525 #undef COUNTER_ENTRY
00526
00527
00528 const char* top_address_format = "Top::get_address_from_id(%i)";
00529 size_t top_format_length = strlen(top_address_format);
00530 for (uint16_t i = 0; i < Top::k_top_address_count; ++i) {
00531 Vector<char> name = Vector<char>::New(top_format_length + 1);
00532 const char* chars = name.start();
00533 OS::SNPrintF(name, top_address_format, i);
00534 Add(Top::get_address_from_id((Top::AddressId)i), TOP_ADDRESS, i, chars);
00535 }
00536
00537
00538 Add(FUNCTION_ADDR(GCExtension::GC), EXTENSION, 1,
00539 "GCExtension::GC");
00540
00541
00542 #define ACCESSOR_DESCRIPTOR_DECLARATION(name) \
00543 Add((Address)&Accessors::name, \
00544 ACCESSOR, \
00545 Accessors::k##name, \
00546 "Accessors::" #name);
00547
00548 ACCESSOR_DESCRIPTOR_LIST(ACCESSOR_DESCRIPTOR_DECLARATION)
00549 #undef ACCESSOR_DESCRIPTOR_DECLARATION
00550
00551
00552 Add(SCTableReference::keyReference(StubCache::kPrimary).address(),
00553 STUB_CACHE_TABLE,
00554 1,
00555 "StubCache::primary_->key");
00556 Add(SCTableReference::valueReference(StubCache::kPrimary).address(),
00557 STUB_CACHE_TABLE,
00558 2,
00559 "StubCache::primary_->value");
00560 Add(SCTableReference::keyReference(StubCache::kSecondary).address(),
00561 STUB_CACHE_TABLE,
00562 3,
00563 "StubCache::secondary_->key");
00564 Add(SCTableReference::valueReference(StubCache::kSecondary).address(),
00565 STUB_CACHE_TABLE,
00566 4,
00567 "StubCache::secondary_->value");
00568
00569
00570 Add(FUNCTION_ADDR(Runtime::PerformGC),
00571 RUNTIME_ENTRY,
00572 1,
00573 "Runtime::PerformGC");
00574
00575
00576 Add(ExternalReference::builtin_passed_function().address(),
00577 UNCLASSIFIED,
00578 1,
00579 "Builtins::builtin_passed_function");
00580 Add(ExternalReference::the_hole_value_location().address(),
00581 UNCLASSIFIED,
00582 2,
00583 "Factory::the_hole_value().location()");
00584 Add(ExternalReference::address_of_stack_guard_limit().address(),
00585 UNCLASSIFIED,
00586 3,
00587 "StackGuard::address_of_limit()");
00588 Add(ExternalReference::debug_break().address(),
00589 UNCLASSIFIED,
00590 4,
00591 "Debug::Break()");
00592 Add(ExternalReference::new_space_start().address(),
00593 UNCLASSIFIED,
00594 5,
00595 "Heap::NewSpaceStart()");
00596 Add(ExternalReference::heap_always_allocate_scope_depth().address(),
00597 UNCLASSIFIED,
00598 6,
00599 "Heap::always_allocate_scope_depth()");
00600 Add(ExternalReference::new_space_allocation_limit_address().address(),
00601 UNCLASSIFIED,
00602 7,
00603 "Heap::NewSpaceAllocationLimitAddress()");
00604 Add(ExternalReference::new_space_allocation_top_address().address(),
00605 UNCLASSIFIED,
00606 8,
00607 "Heap::NewSpaceAllocationTopAddress()");
00608 Add(ExternalReference::debug_step_in_fp_address().address(),
00609 UNCLASSIFIED,
00610 9,
00611 "Debug::step_in_fp_addr()");
00612 }
00613
00614
00615 ExternalReferenceEncoder::ExternalReferenceEncoder()
00616 : encodings_(Match) {
00617 ExternalReferenceTable* external_references =
00618 ExternalReferenceTable::instance();
00619 for (int i = 0; i < external_references->size(); ++i) {
00620 Put(external_references->address(i), i);
00621 }
00622 }
00623
00624
00625 uint32_t ExternalReferenceEncoder::Encode(Address key) const {
00626 int index = IndexOf(key);
00627 return index >=0 ? ExternalReferenceTable::instance()->code(index) : 0;
00628 }
00629
00630
00631 const char* ExternalReferenceEncoder::NameOfAddress(Address key) const {
00632 int index = IndexOf(key);
00633 return index >=0 ? ExternalReferenceTable::instance()->name(index) : NULL;
00634 }
00635
00636
00637 int ExternalReferenceEncoder::IndexOf(Address key) const {
00638 if (key == NULL) return -1;
00639 HashMap::Entry* entry =
00640 const_cast<HashMap &>(encodings_).Lookup(key, Hash(key), false);
00641 return entry == NULL ? -1 : reinterpret_cast<int>(entry->value);
00642 }
00643
00644
00645 void ExternalReferenceEncoder::Put(Address key, int index) {
00646 HashMap::Entry* entry = encodings_.Lookup(key, Hash(key), true);
00647 entry->value = reinterpret_cast<void *>(index);
00648 }
00649
00650
00651 ExternalReferenceDecoder::ExternalReferenceDecoder()
00652 : encodings_(NewArray<Address*>(kTypeCodeCount)) {
00653 ExternalReferenceTable* external_references =
00654 ExternalReferenceTable::instance();
00655 for (int type = kFirstTypeCode; type < kTypeCodeCount; ++type) {
00656 int max = external_references->max_id(type) + 1;
00657 encodings_[type] = NewArray<Address>(max + 1);
00658 }
00659 for (int i = 0; i < external_references->size(); ++i) {
00660 Put(external_references->code(i), external_references->address(i));
00661 }
00662 }
00663
00664
00665 ExternalReferenceDecoder::~ExternalReferenceDecoder() {
00666 for (int type = kFirstTypeCode; type < kTypeCodeCount; ++type) {
00667 DeleteArray(encodings_[type]);
00668 }
00669 DeleteArray(encodings_);
00670 }
00671
00672
00673
00674
00675
00676
00677
00678
00679 class SnapshotWriter {
00680 public:
00681 SnapshotWriter() {
00682 len_ = 0;
00683 max_ = 8 << 10;
00684 str_ = NewArray<char>(max_);
00685 }
00686
00687 ~SnapshotWriter() {
00688 DeleteArray(str_);
00689 }
00690
00691 void GetString(char** str, int* len) {
00692 *str = NewArray<char>(len_);
00693 memcpy(*str, str_, len_);
00694 *len = len_;
00695 }
00696
00697 void Reserve(int bytes, int pos);
00698
00699 void PutC(char c) {
00700 InsertC(c, len_);
00701 }
00702
00703 void PutInt(int i) {
00704 InsertInt(i, len_);
00705 }
00706
00707 void PutBytes(const byte* a, int size) {
00708 InsertBytes(a, len_, size);
00709 }
00710
00711 void PutString(const char* s) {
00712 InsertString(s, len_);
00713 }
00714
00715 int InsertC(char c, int pos) {
00716 Reserve(1, pos);
00717 str_[pos] = c;
00718 len_++;
00719 return pos + 1;
00720 }
00721
00722 int InsertInt(int i, int pos) {
00723 return InsertBytes(reinterpret_cast<byte*>(&i), pos, sizeof(i));
00724 }
00725
00726 int InsertBytes(const byte* a, int pos, int size) {
00727 Reserve(size, pos);
00728 memcpy(&str_[pos], a, size);
00729 len_ += size;
00730 return pos + size;
00731 }
00732
00733 int InsertString(const char* s, int pos);
00734
00735 int length() { return len_; }
00736
00737 Address position() { return reinterpret_cast<Address>(&str_[len_]); }
00738
00739 private:
00740 char* str_;
00741 int len_;
00742 int max_;
00743 };
00744
00745
00746 void SnapshotWriter::Reserve(int bytes, int pos) {
00747 CHECK(0 <= pos && pos <= len_);
00748 while (len_ + bytes >= max_) {
00749 max_ *= 2;
00750 char* old = str_;
00751 str_ = NewArray<char>(max_);
00752 memcpy(str_, old, len_);
00753 DeleteArray(old);
00754 }
00755 if (pos < len_) {
00756 char* old = str_;
00757 str_ = NewArray<char>(max_);
00758 memcpy(str_, old, pos);
00759 memcpy(str_ + pos + bytes, old + pos, len_ - pos);
00760 DeleteArray(old);
00761 }
00762 }
00763
00764 int SnapshotWriter::InsertString(const char* s, int pos) {
00765 int size = strlen(s);
00766 pos = InsertC('[', pos);
00767 pos = InsertInt(size, pos);
00768 pos = InsertC(']', pos);
00769 return InsertBytes(reinterpret_cast<const byte*>(s), pos, size);
00770 }
00771
00772
00773 class ReferenceUpdater: public ObjectVisitor {
00774 public:
00775 ReferenceUpdater(HeapObject* obj, Serializer* serializer)
00776 : obj_address_(obj->address()),
00777 serializer_(serializer),
00778 reference_encoder_(serializer->reference_encoder_),
00779 offsets_(8),
00780 addresses_(8) {
00781 }
00782
00783 virtual void VisitPointers(Object** start, Object** end) {
00784 for (Object** p = start; p < end; ++p) {
00785 if ((*p)->IsHeapObject()) {
00786 offsets_.Add(reinterpret_cast<Address>(p) - obj_address_);
00787 Address a = serializer_->GetSavedAddress(HeapObject::cast(*p));
00788 addresses_.Add(a);
00789 }
00790 }
00791 }
00792
00793 virtual void VisitExternalReferences(Address* start, Address* end) {
00794 for (Address* p = start; p < end; ++p) {
00795 uint32_t code = reference_encoder_->Encode(*p);
00796 CHECK(*p == NULL ? code == 0 : code != 0);
00797 offsets_.Add(reinterpret_cast<Address>(p) - obj_address_);
00798 addresses_.Add(reinterpret_cast<Address>(code));
00799 }
00800 }
00801
00802 virtual void VisitRuntimeEntry(RelocInfo* rinfo) {
00803 Address target = rinfo->target_address();
00804 uint32_t encoding = reference_encoder_->Encode(target);
00805 CHECK(target == NULL ? encoding == 0 : encoding != 0);
00806 offsets_.Add(reinterpret_cast<Address>(rinfo->pc()) - obj_address_);
00807 addresses_.Add(reinterpret_cast<Address>(encoding));
00808 }
00809
00810 void Update(Address start_address) {
00811 for (int i = 0; i < offsets_.length(); i++) {
00812 Address* p = reinterpret_cast<Address*>(start_address + offsets_[i]);
00813 *p = addresses_[i];
00814 }
00815 }
00816
00817 private:
00818 Address obj_address_;
00819 Serializer* serializer_;
00820 ExternalReferenceEncoder* reference_encoder_;
00821 List<int> offsets_;
00822 List<Address> addresses_;
00823 };
00824
00825
00826
00827 static uint32_t HeapObjectHash(HeapObject* key) {
00828 return reinterpret_cast<uint32_t>(key) >> 2;
00829 }
00830
00831
00832 static bool MatchHeapObject(void* key1, void* key2) {
00833 return key1 == key2;
00834 }
00835
00836
00837 Serializer::Serializer()
00838 : global_handles_(4),
00839 saved_addresses_(MatchHeapObject) {
00840 root_ = true;
00841 roots_ = 0;
00842 objects_ = 0;
00843 reference_encoder_ = NULL;
00844 writer_ = new SnapshotWriter();
00845 for (int i = 0; i <= LAST_SPACE; i++) {
00846 allocator_[i] = new SimulatedHeapSpace();
00847 }
00848 }
00849
00850
00851 Serializer::~Serializer() {
00852 for (int i = 0; i <= LAST_SPACE; i++) {
00853 delete allocator_[i];
00854 }
00855 if (reference_encoder_) delete reference_encoder_;
00856 delete writer_;
00857 }
00858
00859
00860 bool Serializer::serialization_enabled_ = true;
00861
00862
00863 #ifdef DEBUG
00864 static const int kMaxTagLength = 32;
00865
00866 void Serializer::Synchronize(const char* tag) {
00867 if (FLAG_debug_serialization) {
00868 int length = strlen(tag);
00869 ASSERT(length <= kMaxTagLength);
00870 writer_->PutC('S');
00871 writer_->PutInt(length);
00872 writer_->PutBytes(reinterpret_cast<const byte*>(tag), length);
00873 }
00874 }
00875 #endif
00876
00877
00878 void Serializer::InitializeAllocators() {
00879 for (int i = 0; i <= LAST_SPACE; i++) {
00880 allocator_[i]->InitEmptyHeap(static_cast<AllocationSpace>(i));
00881 }
00882 }
00883
00884
00885 bool Serializer::IsVisited(HeapObject* obj) {
00886 HashMap::Entry* entry =
00887 saved_addresses_.Lookup(obj, HeapObjectHash(obj), false);
00888 return entry != NULL;
00889 }
00890
00891
00892 Address Serializer::GetSavedAddress(HeapObject* obj) {
00893 HashMap::Entry* entry
00894 = saved_addresses_.Lookup(obj, HeapObjectHash(obj), false);
00895 ASSERT(entry != NULL);
00896 return reinterpret_cast<Address>(entry->value);
00897 }
00898
00899
00900 void Serializer::SaveAddress(HeapObject* obj, Address addr) {
00901 HashMap::Entry* entry =
00902 saved_addresses_.Lookup(obj, HeapObjectHash(obj), true);
00903 entry->value = addr;
00904 }
00905
00906
00907 void Serializer::Serialize() {
00908
00909 CHECK_EQ(NULL, ThreadState::FirstInUse());
00910
00911 CHECK(HandleScopeImplementer::instance()->Blocks()->is_empty());
00912 CHECK_EQ(0, GlobalHandles::NumberOfWeakHandles());
00913
00914
00915 CHECK(StatsTable::HasCounterFunction());
00916 CHECK(enabled());
00917 InitializeAllocators();
00918 reference_encoder_ = new ExternalReferenceEncoder();
00919 PutHeader();
00920 Heap::IterateRoots(this);
00921 PutLog();
00922 PutContextStack();
00923 disable();
00924 }
00925
00926
00927 void Serializer::Finalize(char** str, int* len) {
00928 writer_->GetString(str, len);
00929 }
00930
00931
00932
00933
00934 void Serializer::VisitPointers(Object** start, Object** end) {
00935 bool root = root_;
00936 root_ = false;
00937 for (Object** p = start; p < end; ++p) {
00938 bool serialized;
00939 Address a = Encode(*p, &serialized);
00940 if (root) {
00941 roots_++;
00942
00943
00944 if (!serialized) PutEncodedAddress(a);
00945 }
00946 }
00947 root_ = root;
00948 }
00949
00950
00951 class GlobalHandlesRetriever: public ObjectVisitor {
00952 public:
00953 explicit GlobalHandlesRetriever(List<Object**>* handles)
00954 : global_handles_(handles) {}
00955
00956 virtual void VisitPointers(Object** start, Object** end) {
00957 for (; start != end; ++start) {
00958 global_handles_->Add(start);
00959 }
00960 }
00961
00962 private:
00963 List<Object**>* global_handles_;
00964 };
00965
00966
00967 void Serializer::PutFlags() {
00968 writer_->PutC('F');
00969 List<char*>* argv = FlagList::argv();
00970 writer_->PutInt(argv->length());
00971 writer_->PutC('[');
00972 for (int i = 0; i < argv->length(); i++) {
00973 if (i > 0) writer_->PutC('|');
00974 writer_->PutString((*argv)[i]);
00975 DeleteArray((*argv)[i]);
00976 }
00977 writer_->PutC(']');
00978 flags_end_ = writer_->length();
00979 delete argv;
00980 }
00981
00982
00983 void Serializer::PutHeader() {
00984 PutFlags();
00985 writer_->PutC('D');
00986 #ifdef DEBUG
00987 writer_->PutC(FLAG_debug_serialization ? '1' : '0');
00988 #else
00989 writer_->PutC('0');
00990 #endif
00991
00992
00993 writer_->PutC('S');
00994 writer_->PutC('[');
00995 writer_->PutInt(Heap::old_pointer_space()->Size() +
00996 Heap::new_space()->Size());
00997 writer_->PutC('|');
00998 writer_->PutInt(Heap::old_data_space()->Size() + Heap::new_space()->Size());
00999 writer_->PutC('|');
01000 writer_->PutInt(Heap::code_space()->Size() + Heap::new_space()->Size());
01001 writer_->PutC('|');
01002 writer_->PutInt(Heap::map_space()->Size());
01003 writer_->PutC(']');
01004
01005 writer_->PutC('G');
01006 writer_->PutC('[');
01007 GlobalHandlesRetriever ghr(&global_handles_);
01008 GlobalHandles::IterateRoots(&ghr);
01009 for (int i = 0; i < global_handles_.length(); i++) {
01010 writer_->PutC('N');
01011 }
01012 writer_->PutC(']');
01013 }
01014
01015
01016 void Serializer::PutLog() {
01017 #ifdef ENABLE_LOGGING_AND_PROFILING
01018 if (FLAG_log_code) {
01019 Logger::TearDown();
01020 int pos = writer_->InsertC('L', flags_end_);
01021 bool exists;
01022 Vector<const char> log = ReadFile(FLAG_logfile, &exists);
01023 writer_->InsertString(log.start(), pos);
01024 log.Dispose();
01025 }
01026 #endif
01027 }
01028
01029
01030 static int IndexOf(const List<Object**>& list, Object** element) {
01031 for (int i = 0; i < list.length(); i++) {
01032 if (list[i] == element) return i;
01033 }
01034 return -1;
01035 }
01036
01037
01038 void Serializer::PutGlobalHandleStack(const List<Handle<Object> >& stack) {
01039 writer_->PutC('[');
01040 writer_->PutInt(stack.length());
01041 for (int i = stack.length() - 1; i >= 0; i--) {
01042 writer_->PutC('|');
01043 int gh_index = IndexOf(global_handles_, stack[i].location());
01044 CHECK_GE(gh_index, 0);
01045 writer_->PutInt(gh_index);
01046 }
01047 writer_->PutC(']');
01048 }
01049
01050
01051 void Serializer::PutContextStack() {
01052 List<Handle<Object> > contexts(2);
01053 while (HandleScopeImplementer::instance()->HasSavedContexts()) {
01054 Handle<Object> context =
01055 HandleScopeImplementer::instance()->RestoreContext();
01056 contexts.Add(context);
01057 }
01058 for (int i = contexts.length() - 1; i >= 0; i--) {
01059 HandleScopeImplementer::instance()->SaveContext(contexts[i]);
01060 }
01061 PutGlobalHandleStack(contexts);
01062 }
01063
01064
01065 void Serializer::PutEncodedAddress(Address addr) {
01066 writer_->PutC('P');
01067 writer_->PutInt(reinterpret_cast<int>(addr));
01068 }
01069
01070
01071 Address Serializer::Encode(Object* o, bool* serialized) {
01072 *serialized = false;
01073 if (o->IsSmi()) {
01074 return reinterpret_cast<Address>(o);
01075 } else {
01076 HeapObject* obj = HeapObject::cast(o);
01077 if (IsVisited(obj)) {
01078 return GetSavedAddress(obj);
01079 } else {
01080
01081 *serialized = true;
01082 return PutObject(obj);
01083 }
01084 }
01085 }
01086
01087
01088 Address Serializer::PutObject(HeapObject* obj) {
01089 Map* map = obj->map();
01090 InstanceType type = map->instance_type();
01091 int size = obj->SizeFromMap(map);
01092
01093
01094
01095 Address addr = Allocate(obj).Encode();
01096
01097 SaveAddress(obj, addr);
01098
01099 if (type == CODE_TYPE) {
01100 Code* code = Code::cast(obj);
01101
01102 code->ConvertICTargetsFromAddressToObject();
01103 LOG(CodeMoveEvent(code->address(), addr));
01104 }
01105
01106
01107 writer_->PutC('[');
01108 CHECK_EQ(0, size & kObjectAlignmentMask);
01109 writer_->PutInt(type);
01110 writer_->PutInt(size >> kObjectAlignmentBits);
01111 PutEncodedAddress(addr);
01112
01113
01114
01115 obj->Iterate(this);
01116
01117
01118 writer_->PutC('|');
01119
01120
01121 writer_->PutBytes(obj->address(), size);
01122
01123 ReferenceUpdater updater(obj, this);
01124 obj->Iterate(&updater);
01125 updater.Update(writer_->position() - size);
01126
01127 #ifdef DEBUG
01128 if (FLAG_debug_serialization) {
01129
01130 PutEncodedAddress(addr);
01131 writer_->PutC(']');
01132 }
01133 #endif
01134
01135 if (type == CODE_TYPE) {
01136 Code* code = Code::cast(obj);
01137
01138 code->ConvertICTargetsFromObjectToAddress();
01139 }
01140
01141 objects_++;
01142 return addr;
01143 }
01144
01145
01146 RelativeAddress Serializer::Allocate(HeapObject* obj) {
01147
01148 AllocationSpace s;
01149 bool found = false;
01150 for (int i = FIRST_SPACE; !found && i <= LAST_SPACE; i++) {
01151 s = static_cast<AllocationSpace>(i);
01152 found = Heap::InSpace(obj, s);
01153 }
01154 CHECK(found);
01155 if (s == NEW_SPACE) {
01156 Space* space = Heap::TargetSpace(obj);
01157 ASSERT(space == Heap::old_pointer_space() ||
01158 space == Heap::old_data_space());
01159 s = (space == Heap::old_pointer_space()) ?
01160 OLD_POINTER_SPACE :
01161 OLD_DATA_SPACE;
01162 }
01163 int size = obj->Size();
01164 GCTreatment gc_treatment = DataObject;
01165 if (obj->IsFixedArray()) gc_treatment = PointerObject;
01166 else if (obj->IsCode()) gc_treatment = CodeObject;
01167 return allocator_[s]->Allocate(size, gc_treatment);
01168 }
01169
01170
01171
01172
01173
01174
01175 static const int kInitArraySize = 32;
01176
01177
01178 Deserializer::Deserializer(const char* str, int len)
01179 : reader_(str, len),
01180 map_pages_(kInitArraySize),
01181 old_pointer_pages_(kInitArraySize),
01182 old_data_pages_(kInitArraySize),
01183 code_pages_(kInitArraySize),
01184 large_objects_(kInitArraySize),
01185 global_handles_(4) {
01186 root_ = true;
01187 roots_ = 0;
01188 objects_ = 0;
01189 reference_decoder_ = NULL;
01190 #ifdef DEBUG
01191 expect_debug_information_ = false;
01192 #endif
01193 }
01194
01195
01196 Deserializer::~Deserializer() {
01197 if (reference_decoder_) delete reference_decoder_;
01198 }
01199
01200
01201 void Deserializer::ExpectEncodedAddress(Address expected) {
01202 Address a = GetEncodedAddress();
01203 USE(a);
01204 ASSERT(a == expected);
01205 }
01206
01207
01208 #ifdef DEBUG
01209 void Deserializer::Synchronize(const char* tag) {
01210 if (expect_debug_information_) {
01211 char buf[kMaxTagLength];
01212 reader_.ExpectC('S');
01213 int length = reader_.GetInt();
01214 ASSERT(length <= kMaxTagLength);
01215 reader_.GetBytes(reinterpret_cast<Address>(buf), length);
01216 ASSERT_EQ(strlen(tag), length);
01217 ASSERT(strncmp(tag, buf, length) == 0);
01218 }
01219 }
01220 #endif
01221
01222
01223 void Deserializer::Deserialize() {
01224
01225 ASSERT_EQ(NULL, ThreadState::FirstInUse());
01226
01227 ASSERT(HandleScopeImplementer::instance()->Blocks()->is_empty());
01228 reference_decoder_ = new ExternalReferenceDecoder();
01229
01230
01231 GetHeader();
01232 Heap::IterateRoots(this);
01233 GetContextStack();
01234 }
01235
01236
01237 void Deserializer::VisitPointers(Object** start, Object** end) {
01238 bool root = root_;
01239 root_ = false;
01240 for (Object** p = start; p < end; ++p) {
01241 if (root) {
01242 roots_++;
01243
01244
01245 int c = reader_.GetC();
01246 if (c == '[') {
01247 *p = GetObject();
01248 } else {
01249 ASSERT(c == 'P');
01250 *p = Resolve(reinterpret_cast<Address>(reader_.GetInt()));
01251 }
01252 } else {
01253
01254
01255 *p = Resolve(reinterpret_cast<Address>(*p));
01256 }
01257 }
01258 root_ = root;
01259 }
01260
01261
01262 void Deserializer::VisitExternalReferences(Address* start, Address* end) {
01263 for (Address* p = start; p < end; ++p) {
01264 uint32_t code = reinterpret_cast<uint32_t>(*p);
01265 *p = reference_decoder_->Decode(code);
01266 }
01267 }
01268
01269
01270 void Deserializer::VisitRuntimeEntry(RelocInfo* rinfo) {
01271 uint32_t* pc = reinterpret_cast<uint32_t*>(rinfo->pc());
01272 uint32_t encoding = *pc;
01273 Address target = reference_decoder_->Decode(encoding);
01274 rinfo->set_target_address(target);
01275 }
01276
01277
01278 void Deserializer::GetFlags() {
01279 reader_.ExpectC('F');
01280 int argc = reader_.GetInt() + 1;
01281 char** argv = NewArray<char*>(argc);
01282 reader_.ExpectC('[');
01283 for (int i = 1; i < argc; i++) {
01284 if (i > 1) reader_.ExpectC('|');
01285 argv[i] = reader_.GetString();
01286 }
01287 reader_.ExpectC(']');
01288 has_log_ = false;
01289 for (int i = 1; i < argc; i++) {
01290 if (strcmp("--log_code", argv[i]) == 0) {
01291 has_log_ = true;
01292 } else if (strcmp("--nouse_ic", argv[i]) == 0) {
01293 FLAG_use_ic = false;
01294 } else if (strcmp("--debug_code", argv[i]) == 0) {
01295 FLAG_debug_code = true;
01296 } else if (strcmp("--nolazy", argv[i]) == 0) {
01297 FLAG_lazy = false;
01298 }
01299 DeleteArray(argv[i]);
01300 }
01301
01302 DeleteArray(argv);
01303 }
01304
01305
01306 void Deserializer::GetLog() {
01307 if (has_log_) {
01308 reader_.ExpectC('L');
01309 char* snapshot_log = reader_.GetString();
01310 #ifdef ENABLE_LOGGING_AND_PROFILING
01311 if (FLAG_log_code) {
01312 LOG(Preamble(snapshot_log));
01313 }
01314 #endif
01315 DeleteArray(snapshot_log);
01316 }
01317 }
01318
01319
01320 static void InitPagedSpace(PagedSpace* space,
01321 int capacity,
01322 List<Page*>* page_list) {
01323 space->EnsureCapacity(capacity);
01324
01325
01326 PageIterator it(space, PageIterator::ALL_PAGES);
01327 while (it.has_next()) page_list->Add(it.next());
01328 }
01329
01330
01331 void Deserializer::GetHeader() {
01332 reader_.ExpectC('D');
01333 #ifdef DEBUG
01334 expect_debug_information_ = reader_.GetC() == '1';
01335 #else
01336
01337
01338 if (reader_.GetC() != '0') FATAL("Snapshot contains synchronization tags.");
01339 #endif
01340
01341
01342 reader_.ExpectC('S');
01343 reader_.ExpectC('[');
01344 InitPagedSpace(Heap::old_pointer_space(),
01345 reader_.GetInt(),
01346 &old_pointer_pages_);
01347 reader_.ExpectC('|');
01348 InitPagedSpace(Heap::old_data_space(), reader_.GetInt(), &old_data_pages_);
01349 reader_.ExpectC('|');
01350 InitPagedSpace(Heap::code_space(), reader_.GetInt(), &code_pages_);
01351 reader_.ExpectC('|');
01352 InitPagedSpace(Heap::map_space(), reader_.GetInt(), &map_pages_);
01353 reader_.ExpectC(']');
01354
01355
01356 reader_.ExpectC('G');
01357 reader_.ExpectC('[');
01358 int c = reader_.GetC();
01359 while (c != ']') {
01360 ASSERT(c == 'N');
01361 global_handles_.Add(GlobalHandles::Create(NULL).location());
01362 c = reader_.GetC();
01363 }
01364 }
01365
01366
01367 void Deserializer::GetGlobalHandleStack(List<Handle<Object> >* stack) {
01368 reader_.ExpectC('[');
01369 int length = reader_.GetInt();
01370 for (int i = 0; i < length; i++) {
01371 reader_.ExpectC('|');
01372 int gh_index = reader_.GetInt();
01373 stack->Add(global_handles_[gh_index]);
01374 }
01375 reader_.ExpectC(']');
01376 }
01377
01378
01379 void Deserializer::GetContextStack() {
01380 List<Handle<Object> > entered_contexts(2);
01381 GetGlobalHandleStack(&entered_contexts);
01382 for (int i = 0; i < entered_contexts.length(); i++) {
01383 HandleScopeImplementer::instance()->SaveContext(entered_contexts[i]);
01384 }
01385 }
01386
01387
01388 Address Deserializer::GetEncodedAddress() {
01389 reader_.ExpectC('P');
01390 return reinterpret_cast<Address>(reader_.GetInt());
01391 }
01392
01393
01394 Object* Deserializer::GetObject() {
01395
01396 InstanceType type = static_cast<InstanceType>(reader_.GetInt());
01397 int size = reader_.GetInt() << kObjectAlignmentBits;
01398 Address a = GetEncodedAddress();
01399
01400
01401 AllocationSpace space = GetSpace(a);
01402 Object* o;
01403 if (IsLargeExecutableObject(a)) {
01404 o = Heap::lo_space()->AllocateRawCode(size);
01405 } else if (IsLargeFixedArray(a)) {
01406 o = Heap::lo_space()->AllocateRawFixedArray(size);
01407 } else {
01408 AllocationSpace retry_space = (space == NEW_SPACE)
01409 ? Heap::TargetSpaceId(type)
01410 : space;
01411 o = Heap::AllocateRaw(size, space, retry_space);
01412 }
01413 ASSERT(!o->IsFailure());
01414
01415 ASSERT(o == Resolve(a));
01416
01417
01418 int c = reader_.GetC();
01419 while (c == '[') {
01420 GetObject();
01421 c = reader_.GetC();
01422 }
01423 ASSERT(c == '|');
01424
01425 HeapObject* obj = reinterpret_cast<HeapObject*>(o);
01426
01427 reader_.GetBytes(obj->address(), size);
01428 #ifdef DEBUG
01429 if (expect_debug_information_) {
01430
01431 ExpectEncodedAddress(a);
01432 reader_.ExpectC(']');
01433 }
01434 #endif
01435
01436
01437
01438 VisitPointer(reinterpret_cast<Object**>(obj->address()));
01439 obj->IterateBody(type, size, this);
01440
01441 if (type == CODE_TYPE) {
01442 Code* code = Code::cast(obj);
01443
01444 code->ConvertICTargetsFromObjectToAddress();
01445 LOG(CodeMoveEvent(a, code->address()));
01446 }
01447 objects_++;
01448 return o;
01449 }
01450
01451
01452 static inline Object* ResolvePaged(int page_index,
01453 int page_offset,
01454 PagedSpace* space,
01455 List<Page*>* page_list) {
01456 ASSERT(page_index < page_list->length());
01457 Address address = (*page_list)[page_index]->OffsetToAddress(page_offset);
01458 return HeapObject::FromAddress(address);
01459 }
01460
01461
01462 template<typename T>
01463 void ConcatReversed(List<T>* target, const List<T>& source) {
01464 for (int i = source.length() - 1; i >= 0; i--) {
01465 target->Add(source[i]);
01466 }
01467 }
01468
01469
01470 Object* Deserializer::Resolve(Address encoded) {
01471 Object* o = reinterpret_cast<Object*>(encoded);
01472 if (o->IsSmi()) return o;
01473
01474
01475 ASSERT(o->IsHeapObject());
01476
01477 switch (GetSpace(encoded)) {
01478
01479
01480
01481
01482 case MAP_SPACE:
01483 return ResolvePaged(PageIndex(encoded), PageOffset(encoded),
01484 Heap::map_space(), &map_pages_);
01485 case OLD_POINTER_SPACE:
01486 return ResolvePaged(PageIndex(encoded), PageOffset(encoded),
01487 Heap::old_pointer_space(), &old_pointer_pages_);
01488 case OLD_DATA_SPACE:
01489 return ResolvePaged(PageIndex(encoded), PageOffset(encoded),
01490 Heap::old_data_space(), &old_data_pages_);
01491 case CODE_SPACE:
01492 return ResolvePaged(PageIndex(encoded), PageOffset(encoded),
01493 Heap::code_space(), &code_pages_);
01494 case NEW_SPACE:
01495 return HeapObject::FromAddress(Heap::NewSpaceStart() +
01496 NewSpaceOffset(encoded));
01497 case LO_SPACE:
01498
01499 int index = LargeObjectIndex(encoded);
01500 if (index >= large_objects_.length()) {
01501 int new_object_count =
01502 Heap::lo_space()->PageCount() - large_objects_.length();
01503 List<Object*> new_objects(new_object_count);
01504 LargeObjectIterator it(Heap::lo_space());
01505 for (int i = 0; i < new_object_count; i++) {
01506 new_objects.Add(it.next());
01507 }
01508 #ifdef DEBUG
01509 for (int i = large_objects_.length() - 1; i >= 0; i--) {
01510 ASSERT(it.next() == large_objects_[i]);
01511 }
01512 #endif
01513 ConcatReversed(&large_objects_, new_objects);
01514 ASSERT(index < large_objects_.length());
01515 }
01516 return large_objects_[index];
01517 }
01518 UNREACHABLE();
01519 return NULL;
01520 }
01521
01522
01523 } }