| Index: src/serialize.cc | 
| =================================================================== | 
| --- src/serialize.cc	(revision 4681) | 
| +++ src/serialize.cc	(working copy) | 
| @@ -660,27 +660,164 @@ | 
| } | 
|  | 
|  | 
| -#define ONE_CASE_PER_SPACE(base_tag)   \ | 
| -  case (base_tag) + NEW_SPACE:         /* NOLINT */ \ | 
| -  case (base_tag) + OLD_POINTER_SPACE: /* NOLINT */ \ | 
| -  case (base_tag) + OLD_DATA_SPACE:    /* NOLINT */ \ | 
| -  case (base_tag) + CODE_SPACE:        /* NOLINT */ \ | 
| -  case (base_tag) + MAP_SPACE:         /* NOLINT */ \ | 
| -  case (base_tag) + CELL_SPACE:        /* NOLINT */ \ | 
| -  case (base_tag) + kLargeData:        /* NOLINT */ \ | 
| -  case (base_tag) + kLargeCode:        /* NOLINT */ \ | 
| -  case (base_tag) + kLargeFixedArray:  /* NOLINT */ | 
| +// This macro is always used with a constant argument so it should all fold | 
| +// away to almost nothing in the generated code.  It might be nicer to do this | 
| +// with the ternary operator but there are type issues with that. | 
| +#define ASSIGN_DEST_SPACE(space_number)                                        \ | 
| +  Space* dest_space;                                                           \ | 
| +  if (space_number == NEW_SPACE) {                                             \ | 
| +    dest_space = Heap::new_space();                                            \ | 
| +  } else if (space_number == OLD_POINTER_SPACE) {                              \ | 
| +    dest_space = Heap::old_pointer_space();                                    \ | 
| +  } else if (space_number == OLD_DATA_SPACE) {                                 \ | 
| +    dest_space = Heap::old_data_space();                                       \ | 
| +  } else if (space_number == CODE_SPACE) {                                     \ | 
| +    dest_space = Heap::code_space();                                           \ | 
| +  } else if (space_number == MAP_SPACE) {                                      \ | 
| +    dest_space = Heap::map_space();                                            \ | 
| +  } else if (space_number == CELL_SPACE) {                                     \ | 
| +    dest_space = Heap::cell_space();                                           \ | 
| +  } else {                                                                     \ | 
| +    ASSERT(space_number >= LO_SPACE);                                          \ | 
| +    dest_space = Heap::lo_space();                                             \ | 
| +  } | 
|  | 
|  | 
| +static const int kUnknownOffsetFromStart = -1; | 
| + | 
| + | 
| void Deserializer::ReadChunk(Object** current, | 
| Object** limit, | 
| -                             int space, | 
| +                             int source_space, | 
| Address address) { | 
| while (current < limit) { | 
| int data = source_->Get(); | 
| switch (data) { | 
| +#define CASE_STATEMENT(where, how, within, space_number)                       \ | 
| +      case where + how + within + space_number:                                \ | 
| +      ASSERT((where & ~kPointedToMask) == 0);                                  \ | 
| +      ASSERT((how & ~kHowToCodeMask) == 0);                                    \ | 
| +      ASSERT((within & ~kWhereToPointMask) == 0);                             \ | 
| +      ASSERT((space_number & ~kSpaceMask) == 0); | 
| + | 
| +#define CASE_BODY(where, how, within, space_number_if_any, offset_from_start)  \ | 
| +      {                                                                        \ | 
| +        bool emit_write_barrier = false;                                       \ | 
| +        bool current_was_incremented = false;                                  \ | 
| +        int space_number =  space_number_if_any == kAnyOldSpace ?              \ | 
| +                            (data & kSpaceMask) : space_number_if_any;         \ | 
| +        if (where == kNewObject && how == kPlain && within == kStartOfObject) {\ | 
| +          ASSIGN_DEST_SPACE(space_number)                                      \ | 
| +          ReadObject(space_number, dest_space, current);                       \ | 
| +          emit_write_barrier =                                                 \ | 
| +            (space_number == NEW_SPACE && source_space != NEW_SPACE);          \ | 
| +        } else {                                                               \ | 
| +          Object* new_object = NULL;  /* May not be a real Object pointer. */  \ | 
| +          if (where == kNewObject) {                                           \ | 
| +            ASSIGN_DEST_SPACE(space_number)                                    \ | 
| +            ReadObject(space_number, dest_space, &new_object);                 \ | 
| +          } else if (where == kRootArray) {                                    \ | 
| +            int root_id = source_->GetInt();                                   \ | 
| +            new_object = Heap::roots_address()[root_id];                       \ | 
| +          } else if (where == kPartialSnapshotCache) {                         \ | 
| +            int cache_index = source_->GetInt();                               \ | 
| +            new_object = partial_snapshot_cache_[cache_index];                 \ | 
| +          } else if (where == kExternalReference) {                            \ | 
| +            int reference_id = source_->GetInt();                              \ | 
| +            Address address =                                                  \ | 
| +                external_reference_decoder_->Decode(reference_id);             \ | 
| +            new_object = reinterpret_cast<Object*>(address);                   \ | 
| +          } else if (where == kBackref) {                                      \ | 
| +            emit_write_barrier =                                               \ | 
| +              (space_number == NEW_SPACE && source_space != NEW_SPACE);        \ | 
| +            new_object = GetAddressFromEnd(data & kSpaceMask);                 \ | 
| +          } else {                                                             \ | 
| +            ASSERT(where == kFromStart);                                       \ | 
| +            if (offset_from_start == kUnknownOffsetFromStart) {                \ | 
| +              emit_write_barrier =                                             \ | 
| +                (space_number == NEW_SPACE && source_space != NEW_SPACE);      \ | 
| +              new_object = GetAddressFromStart(data & kSpaceMask);             \ | 
| +            } else {                                                           \ | 
| +              Address object_address = pages_[space_number][0] +               \ | 
| +                  (offset_from_start << kObjectAlignmentBits);                 \ | 
| +              new_object = HeapObject::FromAddress(object_address);            \ | 
| +            }                                                                  \ | 
| +          }                                                                    \ | 
| +          if (within == kFirstInstruction) {                                   \ | 
| +            Code* new_code_object = reinterpret_cast<Code*>(new_object);       \ | 
| +            new_object = reinterpret_cast<Object*>(                            \ | 
| +                new_code_object->instruction_start());                         \ | 
| +          }                                                                    \ | 
| +          if (how == kFromCode) {                                              \ | 
| +            Address location_of_branch_data =                                  \ | 
| +                reinterpret_cast<Address>(current);                            \ | 
| +            Assembler::set_target_at(location_of_branch_data,                  \ | 
| +                                     reinterpret_cast<Address>(new_object));   \ | 
| +            if (within == kFirstInstruction) {                                 \ | 
| +              location_of_branch_data += Assembler::kCallTargetSize;           \ | 
| +              current = reinterpret_cast<Object**>(location_of_branch_data);   \ | 
| +              current_was_incremented = true;                                  \ | 
| +            }                                                                  \ | 
| +          } else {                                                             \ | 
| +            *current = new_object;                                             \ | 
| +          }                                                                    \ | 
| +        }                                                                      \ | 
| +        if (emit_write_barrier) {                                              \ | 
| +          Heap::RecordWrite(address, static_cast<int>(                         \ | 
| +              reinterpret_cast<Address>(current) - address));                  \ | 
| +        }                                                                      \ | 
| +        if (!current_was_incremented) {                                        \ | 
| +          current++;   /* Increment current if it wasn't done above. */        \ | 
| +        }                                                                      \ | 
| +        break;                                                                 \ | 
| +      }                                                                        \ | 
| + | 
| +// This generates a case and a body for each space.  The large object spaces are | 
| +// very rare in snapshots so they are grouped in one body. | 
| +#define ONE_PER_SPACE(where, how, within)                                      \ | 
| +  CASE_STATEMENT(where, how, within, NEW_SPACE)                                \ | 
| +  CASE_BODY(where, how, within, NEW_SPACE, kUnknownOffsetFromStart)            \ | 
| +  CASE_STATEMENT(where, how, within, OLD_DATA_SPACE)                           \ | 
| +  CASE_BODY(where, how, within, OLD_DATA_SPACE, kUnknownOffsetFromStart)       \ | 
| +  CASE_STATEMENT(where, how, within, OLD_POINTER_SPACE)                        \ | 
| +  CASE_BODY(where, how, within, OLD_POINTER_SPACE, kUnknownOffsetFromStart)    \ | 
| +  CASE_STATEMENT(where, how, within, CODE_SPACE)                               \ | 
| +  CASE_BODY(where, how, within, CODE_SPACE, kUnknownOffsetFromStart)           \ | 
| +  CASE_STATEMENT(where, how, within, CELL_SPACE)                               \ | 
| +  CASE_BODY(where, how, within, CELL_SPACE, kUnknownOffsetFromStart)           \ | 
| +  CASE_STATEMENT(where, how, within, MAP_SPACE)                                \ | 
| +  CASE_BODY(where, how, within, MAP_SPACE, kUnknownOffsetFromStart)            \ | 
| +  CASE_STATEMENT(where, how, within, kLargeData)                               \ | 
| +  CASE_STATEMENT(where, how, within, kLargeCode)                               \ | 
| +  CASE_STATEMENT(where, how, within, kLargeFixedArray)                         \ | 
| +  CASE_BODY(where, how, within, kAnyOldSpace, kUnknownOffsetFromStart) | 
| + | 
| +// This generates a case and a body for the new space (which has to do extra | 
| +// write barrier handling) and handles the other spaces with 8 fall-through | 
| +// cases and one body. | 
| +#define ALL_SPACES(where, how, within)                                         \ | 
| +  CASE_STATEMENT(where, how, within, NEW_SPACE)                                \ | 
| +  CASE_BODY(where, how, within, NEW_SPACE, kUnknownOffsetFromStart)            \ | 
| +  CASE_STATEMENT(where, how, within, OLD_DATA_SPACE)                           \ | 
| +  CASE_STATEMENT(where, how, within, OLD_POINTER_SPACE)                        \ | 
| +  CASE_STATEMENT(where, how, within, CODE_SPACE)                               \ | 
| +  CASE_STATEMENT(where, how, within, CELL_SPACE)                               \ | 
| +  CASE_STATEMENT(where, how, within, MAP_SPACE)                                \ | 
| +  CASE_STATEMENT(where, how, within, kLargeData)                               \ | 
| +  CASE_STATEMENT(where, how, within, kLargeCode)                               \ | 
| +  CASE_STATEMENT(where, how, within, kLargeFixedArray)                         \ | 
| +  CASE_BODY(where, how, within, kAnyOldSpace, kUnknownOffsetFromStart) | 
| + | 
| +#define EMIT_COMMON_REFERENCE_PATTERNS(pseudo_space_number,                    \ | 
| +                                       space_number,                           \ | 
| +                                       offset_from_start)                      \ | 
| +  CASE_STATEMENT(kFromStart, kPlain, kStartOfObject, pseudo_space_number)      \ | 
| +  CASE_BODY(kFromStart, kPlain, kStartOfObject, space_number, offset_from_start) | 
| + | 
| +      // We generate 15 cases and bodies that process special tags that combine | 
| +      // the raw data tag and the length into one byte. | 
| #define RAW_CASE(index, size)                                      \ | 
| -      case RAW_DATA_SERIALIZATION + index: {                       \ | 
| +      case kRawData + index: {                                     \ | 
| byte* raw_data_out = reinterpret_cast<byte*>(current);     \ | 
| source_->CopyRaw(raw_data_out, size);                      \ | 
| current = reinterpret_cast<Object**>(raw_data_out + size); \ | 
| @@ -688,144 +825,77 @@ | 
| } | 
| COMMON_RAW_LENGTHS(RAW_CASE) | 
| #undef RAW_CASE | 
| -      case RAW_DATA_SERIALIZATION: { | 
| + | 
| +      // Deserialize a chunk of raw data that doesn't have one of the popular | 
| +      // lengths. | 
| +      case kRawData: { | 
| int size = source_->GetInt(); | 
| byte* raw_data_out = reinterpret_cast<byte*>(current); | 
| source_->CopyRaw(raw_data_out, size); | 
| current = reinterpret_cast<Object**>(raw_data_out + size); | 
| break; | 
| } | 
| -      case OBJECT_SERIALIZATION + NEW_SPACE: { | 
| -        ReadObject(NEW_SPACE, Heap::new_space(), current); | 
| -        if (space != NEW_SPACE) { | 
| -          Heap::RecordWrite(address, static_cast<int>( | 
| -              reinterpret_cast<Address>(current) - address)); | 
| -        } | 
| -        current++; | 
| -        break; | 
| -      } | 
| -      case OBJECT_SERIALIZATION + OLD_DATA_SPACE: | 
| -        ReadObject(OLD_DATA_SPACE, Heap::old_data_space(), current++); | 
| -        break; | 
| -      case OBJECT_SERIALIZATION + OLD_POINTER_SPACE: | 
| -        ReadObject(OLD_POINTER_SPACE, Heap::old_pointer_space(), current++); | 
| -        break; | 
| -      case OBJECT_SERIALIZATION + MAP_SPACE: | 
| -        ReadObject(MAP_SPACE, Heap::map_space(), current++); | 
| -        break; | 
| -      case OBJECT_SERIALIZATION + CODE_SPACE: | 
| -        ReadObject(CODE_SPACE, Heap::code_space(), current++); | 
| -        break; | 
| -      case OBJECT_SERIALIZATION + CELL_SPACE: | 
| -        ReadObject(CELL_SPACE, Heap::cell_space(), current++); | 
| -        break; | 
| -      case OBJECT_SERIALIZATION + kLargeData: | 
| -        ReadObject(kLargeData, Heap::lo_space(), current++); | 
| -        break; | 
| -      case OBJECT_SERIALIZATION + kLargeCode: | 
| -        ReadObject(kLargeCode, Heap::lo_space(), current++); | 
| -        break; | 
| -      case OBJECT_SERIALIZATION + kLargeFixedArray: | 
| -        ReadObject(kLargeFixedArray, Heap::lo_space(), current++); | 
| -        break; | 
| -      case CODE_OBJECT_SERIALIZATION + kLargeCode: { | 
| -        Object* new_code_object = NULL; | 
| -        ReadObject(kLargeCode, Heap::lo_space(), &new_code_object); | 
| -        Code* code_object = reinterpret_cast<Code*>(new_code_object); | 
| -        // Setting a branch/call to another code object from code. | 
| -        Address location_of_branch_data = reinterpret_cast<Address>(current); | 
| -        Assembler::set_target_at(location_of_branch_data, | 
| -                                 code_object->instruction_start()); | 
| -        location_of_branch_data += Assembler::kCallTargetSize; | 
| -        current = reinterpret_cast<Object**>(location_of_branch_data); | 
| -        break; | 
| -      } | 
| -      case CODE_OBJECT_SERIALIZATION + CODE_SPACE: { | 
| -        Object* new_code_object = NULL; | 
| -        ReadObject(CODE_SPACE, Heap::code_space(), &new_code_object); | 
| -        Code* code_object = reinterpret_cast<Code*>(new_code_object); | 
| -        // Setting a branch/call to another code object from code. | 
| -        Address location_of_branch_data = reinterpret_cast<Address>(current); | 
| -        Assembler::set_target_at(location_of_branch_data, | 
| -                                 code_object->instruction_start()); | 
| -        location_of_branch_data += Assembler::kCallTargetSize; | 
| -        current = reinterpret_cast<Object**>(location_of_branch_data); | 
| -        break; | 
| -      } | 
| -      ONE_CASE_PER_SPACE(BACKREF_SERIALIZATION) { | 
| -        // Write a backreference to an object we unpacked earlier. | 
| -        int backref_space = (data & kSpaceMask); | 
| -        if (backref_space == NEW_SPACE && space != NEW_SPACE) { | 
| -          Heap::RecordWrite(address, static_cast<int>( | 
| -              reinterpret_cast<Address>(current) - address)); | 
| -        } | 
| -        *current++ = GetAddressFromEnd(backref_space); | 
| -        break; | 
| -      } | 
| -      ONE_CASE_PER_SPACE(REFERENCE_SERIALIZATION) { | 
| -        // Write a reference to an object we unpacked earlier. | 
| -        int reference_space = (data & kSpaceMask); | 
| -        if (reference_space == NEW_SPACE && space != NEW_SPACE) { | 
| -          Heap::RecordWrite(address, static_cast<int>( | 
| -              reinterpret_cast<Address>(current) - address)); | 
| -        } | 
| -        *current++ = GetAddressFromStart(reference_space); | 
| -        break; | 
| -      } | 
| -#define COMMON_REFS_CASE(index, reference_space, address)                      \ | 
| -      case REFERENCE_SERIALIZATION + index: {                                  \ | 
| -        ASSERT(SpaceIsPaged(reference_space));                                 \ | 
| -        Address object_address =                                               \ | 
| -            pages_[reference_space][0] + (address << kObjectAlignmentBits);    \ | 
| -        *current++ = HeapObject::FromAddress(object_address);                  \ | 
| -        break;                                                                 \ | 
| -      } | 
| -      COMMON_REFERENCE_PATTERNS(COMMON_REFS_CASE) | 
| -#undef COMMON_REFS_CASE | 
| -      ONE_CASE_PER_SPACE(CODE_BACKREF_SERIALIZATION) { | 
| -        int backref_space = (data & kSpaceMask); | 
| -        // Can't use Code::cast because heap is not set up yet and assertions | 
| -        // will fail. | 
| -        Code* code_object = | 
| -            reinterpret_cast<Code*>(GetAddressFromEnd(backref_space)); | 
| -        // Setting a branch/call to previously decoded code object from code. | 
| -        Address location_of_branch_data = reinterpret_cast<Address>(current); | 
| -        Assembler::set_target_at(location_of_branch_data, | 
| -                                 code_object->instruction_start()); | 
| -        location_of_branch_data += Assembler::kCallTargetSize; | 
| -        current = reinterpret_cast<Object**>(location_of_branch_data); | 
| -        break; | 
| -      } | 
| -      ONE_CASE_PER_SPACE(CODE_REFERENCE_SERIALIZATION) { | 
| -        int backref_space = (data & kSpaceMask); | 
| -        // Can't use Code::cast because heap is not set up yet and assertions | 
| -        // will fail. | 
| -        Code* code_object = | 
| -            reinterpret_cast<Code*>(GetAddressFromStart(backref_space)); | 
| -        // Setting a branch/call to previously decoded code object from code. | 
| -        Address location_of_branch_data = reinterpret_cast<Address>(current); | 
| -        Assembler::set_target_at(location_of_branch_data, | 
| -                                 code_object->instruction_start()); | 
| -        location_of_branch_data += Assembler::kCallTargetSize; | 
| -        current = reinterpret_cast<Object**>(location_of_branch_data); | 
| -        break; | 
| -      } | 
| -      case EXTERNAL_REFERENCE_SERIALIZATION: { | 
| -        int reference_id = source_->GetInt(); | 
| -        Address address = external_reference_decoder_->Decode(reference_id); | 
| -        *current++ = reinterpret_cast<Object*>(address); | 
| -        break; | 
| -      } | 
| -      case EXTERNAL_BRANCH_TARGET_SERIALIZATION: { | 
| -        int reference_id = source_->GetInt(); | 
| -        Address address = external_reference_decoder_->Decode(reference_id); | 
| -        Address location_of_branch_data = reinterpret_cast<Address>(current); | 
| -        Assembler::set_external_target_at(location_of_branch_data, address); | 
| -        location_of_branch_data += Assembler::kExternalTargetSize; | 
| -        current = reinterpret_cast<Object**>(location_of_branch_data); | 
| -        break; | 
| -      } | 
| -      case START_NEW_PAGE_SERIALIZATION: { | 
| + | 
| +      // Deserialize a new object and write a pointer to it to the current | 
| +      // object. | 
| +      ONE_PER_SPACE(kNewObject, kPlain, kStartOfObject) | 
| +      // Deserialize a new code object and write a pointer to its first | 
| +      // instruction to the current code object. | 
| +      ONE_PER_SPACE(kNewObject, kFromCode, kFirstInstruction) | 
| +      // Find a recently deserialized object using its offset from the current | 
| +      // allocation point and write a pointer to it to the current object. | 
| +      ALL_SPACES(kBackref, kPlain, kStartOfObject) | 
| +      // Find a recently deserialized code object using its offset from the | 
| +      // current allocation point and write a pointer to its first instruction | 
| +      // to the current code object. | 
| +      ALL_SPACES(kBackref, kFromCode, kFirstInstruction) | 
| +      // Find an already deserialized object using its offset from the start | 
| +      // and write a pointer to it to the current object. | 
| +      ALL_SPACES(kFromStart, kPlain, kStartOfObject) | 
| +      // Find an already deserialized code object using its offset from the | 
| +      // start and write a pointer to its first instruction to the current code | 
| +      // object. | 
| +      ALL_SPACES(kFromStart, kFromCode, kFirstInstruction) | 
| +      // Find an already deserialized object at one of the predetermined popular | 
| +      // offsets from the start and write a pointer to it in the current object. | 
| +      COMMON_REFERENCE_PATTERNS(EMIT_COMMON_REFERENCE_PATTERNS) | 
| +      // Find an object in the roots array and write a pointer to it to the | 
| +      // current object. | 
| +      CASE_STATEMENT(kRootArray, kPlain, kStartOfObject, 0) | 
| +      CASE_BODY(kRootArray, kPlain, kStartOfObject, 0, kUnknownOffsetFromStart) | 
| +      // Find an object in the partial snapshots cache and write a pointer to it | 
| +      // to the current object. | 
| +      CASE_STATEMENT(kPartialSnapshotCache, kPlain, kStartOfObject, 0) | 
| +      CASE_BODY(kPartialSnapshotCache, | 
| +                kPlain, | 
| +                kStartOfObject, | 
| +                0, | 
| +                kUnknownOffsetFromStart) | 
| +      // Find an external reference and write a pointer to it to the current | 
| +      // object. | 
| +      CASE_STATEMENT(kExternalReference, kPlain, kStartOfObject, 0) | 
| +      CASE_BODY(kExternalReference, | 
| +                kPlain, | 
| +                kStartOfObject, | 
| +                0, | 
| +                kUnknownOffsetFromStart) | 
| +      // Find an external reference and write a pointer to it in the current | 
| +      // code object. | 
| +      CASE_STATEMENT(kExternalReference, kFromCode, kStartOfObject, 0) | 
| +      CASE_BODY(kExternalReference, | 
| +                kFromCode, | 
| +                kStartOfObject, | 
| +                0, | 
| +                kUnknownOffsetFromStart) | 
| + | 
| +#undef CASE_STATEMENT | 
| +#undef CASE_BODY | 
| +#undef ONE_PER_SPACE | 
| +#undef ALL_SPACES | 
| +#undef EMIT_COMMON_REFERENCE_PATTERNS | 
| +#undef ASSIGN_DEST_SPACE | 
| + | 
| +      case kNewPage: { | 
| int space = source_->Get(); | 
| pages_[space].Add(last_object_address_); | 
| if (space == CODE_SPACE) { | 
| @@ -833,7 +903,8 @@ | 
| } | 
| break; | 
| } | 
| -      case NATIVES_STRING_RESOURCE: { | 
| + | 
| +      case kNativesStringResource: { | 
| int index = source_->Get(); | 
| Vector<const char> source_vector = Natives::GetScriptSource(index); | 
| NativesExternalStringResource* resource = | 
| @@ -841,21 +912,13 @@ | 
| *current++ = reinterpret_cast<Object*>(resource); | 
| break; | 
| } | 
| -      case ROOT_SERIALIZATION: { | 
| -        int root_id = source_->GetInt(); | 
| -        *current++ = Heap::roots_address()[root_id]; | 
| -        break; | 
| -      } | 
| -      case PARTIAL_SNAPSHOT_CACHE_ENTRY: { | 
| -        int cache_index = source_->GetInt(); | 
| -        *current++ = partial_snapshot_cache_[cache_index]; | 
| -        break; | 
| -      } | 
| -      case SYNCHRONIZE: { | 
| + | 
| +      case kSynchronize: { | 
| // If we get here then that indicates that you have a mismatch between | 
| // the number of GC roots when serializing and deserializing. | 
| UNREACHABLE(); | 
| } | 
| + | 
| default: | 
| UNREACHABLE(); | 
| } | 
| @@ -880,7 +943,7 @@ | 
| int data = source_->Get(); | 
| // If this assert fails then that indicates that you have a mismatch between | 
| // the number of GC roots when serializing and deserializing. | 
| -  ASSERT_EQ(SYNCHRONIZE, data); | 
| +  ASSERT_EQ(kSynchronize, data); | 
| do { | 
| int character = source_->Get(); | 
| if (character == 0) break; | 
| @@ -895,7 +958,7 @@ | 
|  | 
|  | 
| void Serializer::Synchronize(const char* tag) { | 
| -  sink_->Put(SYNCHRONIZE, tag); | 
| +  sink_->Put(kSynchronize, tag); | 
| int character; | 
| do { | 
| character = *tag++; | 
| @@ -957,13 +1020,13 @@ | 
| void Serializer::VisitPointers(Object** start, Object** end) { | 
| for (Object** current = start; current < end; current++) { | 
| if ((*current)->IsSmi()) { | 
| -      sink_->Put(RAW_DATA_SERIALIZATION, "RawData"); | 
| +      sink_->Put(kRawData, "RawData"); | 
| sink_->PutInt(kPointerSize, "length"); | 
| for (int i = 0; i < kPointerSize; i++) { | 
| sink_->Put(reinterpret_cast<byte*>(current)[i], "Byte"); | 
| } | 
| } else { | 
| -      SerializeObject(*current, TAGGED_REPRESENTATION); | 
| +      SerializeObject(*current, kPlain, kStartOfObject); | 
| } | 
| } | 
| } | 
| @@ -1033,7 +1096,8 @@ | 
| void Serializer::SerializeReferenceToPreviousObject( | 
| int space, | 
| int address, | 
| -    ReferenceRepresentation reference_representation) { | 
| +    HowToCode how_to_code, | 
| +    WhereToPoint where_to_point) { | 
| int offset = CurrentAllocationAddress(space) - address; | 
| bool from_start = true; | 
| if (SpaceIsPaged(space)) { | 
| @@ -1054,43 +1118,30 @@ | 
| // If we are actually dealing with real offsets (and not a numbering of | 
| // all objects) then we should shift out the bits that are always 0. | 
| if (!SpaceIsLarge(space)) address >>= kObjectAlignmentBits; | 
| -  // On some architectures references between code objects are encoded | 
| -  // specially (as relative offsets).  Such references have their own | 
| -  // special tags to simplify the deserializer. | 
| -  if (reference_representation == CODE_TARGET_REPRESENTATION) { | 
| -    if (from_start) { | 
| -      sink_->Put(CODE_REFERENCE_SERIALIZATION + space, "RefCodeSer"); | 
| +  if (from_start) { | 
| +#define COMMON_REFS_CASE(pseudo_space, actual_space, offset)                   \ | 
| +    if (space == actual_space && address == offset &&                          \ | 
| +        how_to_code == kPlain && where_to_point == kStartOfObject) {           \ | 
| +      sink_->Put(kFromStart + how_to_code + where_to_point +                   \ | 
| +                 pseudo_space, "RefSer");                                      \ | 
| +    } else  /* NOLINT */ | 
| +    COMMON_REFERENCE_PATTERNS(COMMON_REFS_CASE) | 
| +#undef COMMON_REFS_CASE | 
| +    {  /* NOLINT */ | 
| +      sink_->Put(kFromStart + how_to_code + where_to_point + space, "RefSer"); | 
| sink_->PutInt(address, "address"); | 
| -    } else { | 
| -      sink_->Put(CODE_BACKREF_SERIALIZATION + space, "BackRefCodeSer"); | 
| -      sink_->PutInt(address, "address"); | 
| } | 
| } else { | 
| -    // Regular absolute references. | 
| -    CHECK_EQ(TAGGED_REPRESENTATION, reference_representation); | 
| -    if (from_start) { | 
| -      // There are some common offsets that have their own specialized encoding. | 
| -#define COMMON_REFS_CASE(tag, common_space, common_offset)               \ | 
| -      if (space == common_space && address == common_offset) {           \ | 
| -        sink_->PutSection(tag + REFERENCE_SERIALIZATION, "RefSer");      \ | 
| -      } else  /* NOLINT */ | 
| -      COMMON_REFERENCE_PATTERNS(COMMON_REFS_CASE) | 
| -#undef COMMON_REFS_CASE | 
| -      {  /* NOLINT */ | 
| -        sink_->Put(REFERENCE_SERIALIZATION + space, "RefSer"); | 
| -        sink_->PutInt(address, "address"); | 
| -      } | 
| -    } else { | 
| -      sink_->Put(BACKREF_SERIALIZATION + space, "BackRefSer"); | 
| -      sink_->PutInt(address, "address"); | 
| -    } | 
| +    sink_->Put(kBackref + how_to_code + where_to_point + space, "BackRefSer"); | 
| +    sink_->PutInt(address, "address"); | 
| } | 
| } | 
|  | 
|  | 
| void StartupSerializer::SerializeObject( | 
| Object* o, | 
| -    ReferenceRepresentation reference_representation) { | 
| +    HowToCode how_to_code, | 
| +    WhereToPoint where_to_point) { | 
| CHECK(o->IsHeapObject()); | 
| HeapObject* heap_object = HeapObject::cast(o); | 
|  | 
| @@ -1099,13 +1150,15 @@ | 
| int address = address_mapper_.MappedTo(heap_object); | 
| SerializeReferenceToPreviousObject(space, | 
| address, | 
| -                                       reference_representation); | 
| +                                       how_to_code, | 
| +                                       where_to_point); | 
| } else { | 
| // Object has not yet been serialized.  Serialize it here. | 
| ObjectSerializer object_serializer(this, | 
| heap_object, | 
| sink_, | 
| -                                       reference_representation); | 
| +                                       how_to_code, | 
| +                                       where_to_point); | 
| object_serializer.Serialize(); | 
| } | 
| } | 
| @@ -1115,7 +1168,7 @@ | 
| for (int i = partial_snapshot_cache_length_; | 
| i < kPartialSnapshotCacheCapacity; | 
| i++) { | 
| -    sink_->Put(ROOT_SERIALIZATION, "RootSerialization"); | 
| +    sink_->Put(kRootArray + kPlain + kStartOfObject, "RootSerialization"); | 
| sink_->PutInt(Heap::kUndefinedValueRootIndex, "root_index"); | 
| } | 
| Heap::IterateWeakRoots(this, VISIT_ALL); | 
| @@ -1124,20 +1177,22 @@ | 
|  | 
| void PartialSerializer::SerializeObject( | 
| Object* o, | 
| -    ReferenceRepresentation reference_representation) { | 
| +    HowToCode how_to_code, | 
| +    WhereToPoint where_to_point) { | 
| CHECK(o->IsHeapObject()); | 
| HeapObject* heap_object = HeapObject::cast(o); | 
|  | 
| int root_index; | 
| if ((root_index = RootIndex(heap_object)) != kInvalidRootIndex) { | 
| -    sink_->Put(ROOT_SERIALIZATION, "RootSerialization"); | 
| +    sink_->Put(kRootArray + how_to_code + where_to_point, "RootSerialization"); | 
| sink_->PutInt(root_index, "root_index"); | 
| return; | 
| } | 
|  | 
| if (ShouldBeInThePartialSnapshotCache(heap_object)) { | 
| int cache_index = PartialSnapshotCacheIndex(heap_object); | 
| -    sink_->Put(PARTIAL_SNAPSHOT_CACHE_ENTRY, "PartialSnapshotCache"); | 
| +    sink_->Put(kPartialSnapshotCache + how_to_code + where_to_point, | 
| +               "PartialSnapshotCache"); | 
| sink_->PutInt(cache_index, "partial_snapshot_cache_index"); | 
| return; | 
| } | 
| @@ -1155,13 +1210,15 @@ | 
| int address = address_mapper_.MappedTo(heap_object); | 
| SerializeReferenceToPreviousObject(space, | 
| address, | 
| -                                       reference_representation); | 
| +                                       how_to_code, | 
| +                                       where_to_point); | 
| } else { | 
| // Object has not yet been serialized.  Serialize it here. | 
| ObjectSerializer serializer(this, | 
| heap_object, | 
| sink_, | 
| -                                reference_representation); | 
| +                                how_to_code, | 
| +                                where_to_point); | 
| serializer.Serialize(); | 
| } | 
| } | 
| @@ -1171,12 +1228,8 @@ | 
| int space = Serializer::SpaceOfObject(object_); | 
| int size = object_->Size(); | 
|  | 
| -  if (reference_representation_ == TAGGED_REPRESENTATION) { | 
| -    sink_->Put(OBJECT_SERIALIZATION + space, "ObjectSerialization"); | 
| -  } else { | 
| -    CHECK_EQ(CODE_TARGET_REPRESENTATION, reference_representation_); | 
| -    sink_->Put(CODE_OBJECT_SERIALIZATION + space, "ObjectSerialization"); | 
| -  } | 
| +  sink_->Put(kNewObject + reference_representation_ + space, | 
| +             "ObjectSerialization"); | 
| sink_->PutInt(size >> kObjectAlignmentBits, "Size in words"); | 
|  | 
| LOG(SnapshotPositionEvent(object_->address(), sink_->Position())); | 
| @@ -1186,12 +1239,12 @@ | 
| int offset = serializer_->Allocate(space, size, &start_new_page); | 
| serializer_->address_mapper()->AddMapping(object_, offset); | 
| if (start_new_page) { | 
| -    sink_->Put(START_NEW_PAGE_SERIALIZATION, "NewPage"); | 
| +    sink_->Put(kNewPage, "NewPage"); | 
| sink_->PutSection(space, "NewPageSpace"); | 
| } | 
|  | 
| // Serialize the map (first word of the object). | 
| -  serializer_->SerializeObject(object_->map(), TAGGED_REPRESENTATION); | 
| +  serializer_->SerializeObject(object_->map(), kPlain, kStartOfObject); | 
|  | 
| // Serialize the rest of the object. | 
| CHECK_EQ(0, bytes_processed_so_far_); | 
| @@ -1209,7 +1262,7 @@ | 
| if (current < end) OutputRawData(reinterpret_cast<Address>(current)); | 
|  | 
| while (current < end && !(*current)->IsSmi()) { | 
| -      serializer_->SerializeObject(*current, TAGGED_REPRESENTATION); | 
| +      serializer_->SerializeObject(*current, kPlain, kStartOfObject); | 
| bytes_processed_so_far_ += kPointerSize; | 
| current++; | 
| } | 
| @@ -1223,7 +1276,7 @@ | 
| OutputRawData(references_start); | 
|  | 
| for (Address* current = start; current < end; current++) { | 
| -    sink_->Put(EXTERNAL_REFERENCE_SERIALIZATION, "ExternalReference"); | 
| +    sink_->Put(kExternalReference + kPlain + kStartOfObject, "ExternalRef"); | 
| int reference_id = serializer_->EncodeExternalReference(*current); | 
| sink_->PutInt(reference_id, "reference id"); | 
| } | 
| @@ -1237,7 +1290,14 @@ | 
| Address target = rinfo->target_address(); | 
| uint32_t encoding = serializer_->EncodeExternalReference(target); | 
| CHECK(target == NULL ? encoding == 0 : encoding != 0); | 
| -  sink_->Put(EXTERNAL_BRANCH_TARGET_SERIALIZATION, "ExternalReference"); | 
| +  int representation; | 
| +  // Can't use a ternary operator because of gcc. | 
| +  if (rinfo->IsCodedSpecially()) { | 
| +    representation = kStartOfObject + kFromCode; | 
| +  } else { | 
| +    representation = kStartOfObject + kPlain; | 
| +  } | 
| +  sink_->Put(kExternalReference + representation, "ExternalReference"); | 
| sink_->PutInt(encoding, "reference id"); | 
| bytes_processed_so_far_ += Assembler::kExternalTargetSize; | 
| } | 
| @@ -1248,7 +1308,7 @@ | 
| Address target_start = rinfo->target_address_address(); | 
| OutputRawData(target_start); | 
| Code* target = Code::GetCodeFromTargetAddress(rinfo->target_address()); | 
| -  serializer_->SerializeObject(target, CODE_TARGET_REPRESENTATION); | 
| +  serializer_->SerializeObject(target, kFromCode, kFirstInstruction); | 
| bytes_processed_so_far_ += Assembler::kCallTargetSize; | 
| } | 
|  | 
| @@ -1264,7 +1324,7 @@ | 
| typedef v8::String::ExternalAsciiStringResource Resource; | 
| Resource* resource = string->resource(); | 
| if (resource == *resource_pointer) { | 
| -        sink_->Put(NATIVES_STRING_RESOURCE, "NativesStringResource"); | 
| +        sink_->Put(kNativesStringResource, "NativesStringResource"); | 
| sink_->PutSection(i, "NativesStringResourceEnd"); | 
| bytes_processed_so_far_ += sizeof(resource); | 
| return; | 
| @@ -1288,12 +1348,12 @@ | 
| Address base = object_start + bytes_processed_so_far_; | 
| #define RAW_CASE(index, length)                                                \ | 
| if (skipped == length) {                                                   \ | 
| -      sink_->PutSection(RAW_DATA_SERIALIZATION + index, "RawDataFixed");       \ | 
| +      sink_->PutSection(kRawData + index, "RawDataFixed");                     \ | 
| } else  /* NOLINT */ | 
| COMMON_RAW_LENGTHS(RAW_CASE) | 
| #undef RAW_CASE | 
| {  /* NOLINT */ | 
| -      sink_->Put(RAW_DATA_SERIALIZATION, "RawData"); | 
| +      sink_->Put(kRawData, "RawData"); | 
| sink_->PutInt(skipped, "length"); | 
| } | 
| for (int i = 0; i < skipped; i++) { | 
|  |