Remove all uses of StringShape variables, since that has proven
authorerik.corry@gmail.com <erik.corry@gmail.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 17 Mar 2009 09:33:06 +0000 (09:33 +0000)
committererik.corry@gmail.com <erik.corry@gmail.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 17 Mar 2009 09:33:06 +0000 (09:33 +0000)
to be error-prone and of little benefit in terms of performance.
Review URL: http://codereview.chromium.org/45010

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@1521 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

23 files changed:
src/api.cc
src/codegen.cc
src/conversions.cc
src/factory.cc
src/factory.h
src/handles.cc
src/heap.cc
src/heap.h
src/interpreter-irregexp.cc
src/jsregexp.cc
src/jsregexp.h
src/log.cc
src/objects-debug.cc
src/objects-inl.h
src/objects.cc
src/objects.h
src/parser.cc
src/prettyprinter.cc
src/regexp-macro-assembler-ia32.cc
src/runtime.cc
test/cctest/test-heap.cc
test/cctest/test-regexp.cc
test/cctest/test-strings.cc

index bb0747a..985c60d 100644 (file)
@@ -2034,7 +2034,7 @@ int String::WriteAscii(char* buffer, int start, int length) const {
   i::Handle<i::String> str = Utils::OpenHandle(this);
   // Flatten the string for efficiency.  This applies whether we are
   // using StringInputBuffer or Get(i) to access the characters.
-  str->TryFlattenIfNotFlat(i::StringShape(*str));
+  str->TryFlattenIfNotFlat();
   int end = length;
   if ( (length == -1) || (length > str->length() - start) )
     end = str->length() - start;
@@ -2059,7 +2059,7 @@ int String::Write(uint16_t* buffer, int start, int length) const {
   i::Handle<i::String> str = Utils::OpenHandle(this);
   // Flatten the string for efficiency.  This applies whether we are
   // using StringInputBuffer or Get(i) to access the characters.
-  str->TryFlattenIfNotFlat(i::StringShape(*str));
+  str->TryFlattenIfNotFlat();
   int end = length;
   if ( (length == -1) || (length > str->length() - start) )
     end = str->length() - start;
@@ -2077,16 +2077,14 @@ int String::Write(uint16_t* buffer, int start, int length) const {
 bool v8::String::IsExternal() const {
   EnsureInitialized("v8::String::IsExternal()");
   i::Handle<i::String> str = Utils::OpenHandle(this);
-  i::StringShape shape(*str);
-  return shape.IsExternalTwoByte();
+  return i::StringShape(*str).IsExternalTwoByte();
 }
 
 
 bool v8::String::IsExternalAscii() const {
   EnsureInitialized("v8::String::IsExternalAscii()");
   i::Handle<i::String> str = Utils::OpenHandle(this);
-  i::StringShape shape(*str);
-  return shape.IsExternalAscii();
+  return i::StringShape(*str).IsExternalAscii();
 }
 
 
index 558e854..0e623ac 100644 (file)
@@ -402,8 +402,7 @@ bool CodeGenerator::CheckForInlineRuntimeCall(CallRuntime* node) {
      "_Log"}
   };
   Handle<String> name = node->name();
-  StringShape shape(*name);
-  if (name->length(shape) > 0 && name->Get(shape, 0) == '_') {
+  if (name->length() > 0 && name->Get(0) == '_') {
     for (unsigned i = 0;
          i < sizeof(kInlineRuntimeLUT) / sizeof(InlineRuntimeLUT);
          i++) {
index 4b4faa5..57a4568 100644 (file)
@@ -55,8 +55,7 @@ static inline int GetChar(const char* str, int index) {
 
 
 static inline int GetChar(String* str, int index) {
-  StringShape shape(str);
-  return str->Get(shape, index);
+  return str->Get(index);
 }
 
 
@@ -76,11 +75,10 @@ static inline const char* GetCString(const char* str, int index) {
 
 
 static inline const char* GetCString(String* str, int index) {
-  StringShape shape(str);
-  int length = str->length(shape);
+  int length = str->length();
   char* result = NewArray<char>(length + 1);
   for (int i = index; i < length; i++) {
-    uc16 c = str->Get(shape, i);
+    uc16 c = str->Get(i);
     if (c <= 127) {
       result[i - index] = static_cast<char>(c);
     } else {
@@ -108,8 +106,7 @@ static inline bool IsSpace(const char* str, int index) {
 
 
 static inline bool IsSpace(String* str, int index) {
-  StringShape shape(str);
-  return Scanner::kIsWhiteSpace.get(str->Get(shape, index));
+  return Scanner::kIsWhiteSpace.get(str->Get(index));
 }
 
 
index ead40b4..e29c84d 100644 (file)
@@ -90,11 +90,9 @@ Handle<String> Factory::NewRawTwoByteString(int length,
 
 
 Handle<String> Factory::NewConsString(Handle<String> first,
-                                      StringShape first_shape,
-                                      Handle<String> second,
-                                      StringShape second_shape) {
-  if (first->length(first_shape) == 0) return second;
-  if (second->length(second_shape) == 0) return first;
+                                      Handle<String> second) {
+  if (first->length() == 0) return second;
+  if (second->length() == 0) return first;
   CALL_HEAP_FUNCTION(Heap::AllocateConsString(*first, *second), String);
 }
 
index 754c6da..38d1a5b 100644 (file)
@@ -98,9 +98,7 @@ class Factory : public AllStatic {
 
   // Create a new cons string object which consists of a pair of strings.
   static Handle<String> NewConsString(Handle<String> first,
-                                      StringShape first_shape,
-                                      Handle<String> second,
-                                      StringShape second_shape);
+                                      Handle<String> second);
 
   // Create a new sliced string object which represents a substring of a
   // backing string.
index 48065dd..41323ed 100644 (file)
@@ -186,8 +186,8 @@ void TransformToFastProperties(Handle<JSObject> object,
 
 
 void FlattenString(Handle<String> string) {
-  CALL_HEAP_FUNCTION_VOID(string->TryFlattenIfNotFlat(StringShape(*string)));
-  ASSERT(string->IsFlat(StringShape(*string)));
+  CALL_HEAP_FUNCTION_VOID(string->TryFlattenIfNotFlat());
+  ASSERT(string->IsFlat());
 }
 
 
index eade646..daefaaf 100644 (file)
@@ -230,7 +230,6 @@ void Heap::ReportStatisticsAfterGC() {
 
 
 void Heap::GarbageCollectionPrologue() {
-  RegExpImpl::NewSpaceCollectionPrologue();
   gc_count_++;
 #ifdef DEBUG
   ASSERT(allocation_allowed_ && gc_state_ == NOT_IN_GC);
@@ -475,7 +474,6 @@ void Heap::MarkCompactPrologue(bool is_compacting) {
   ClearKeyedLookupCache();
 
   CompilationCache::MarkCompactPrologue();
-  RegExpImpl::OldSpaceCollectionPrologue();
 
   Top::MarkCompactPrologue(is_compacting);
   ThreadManager::MarkCompactPrologue(is_compacting);
@@ -1392,41 +1390,31 @@ Object* Heap::AllocateSharedFunctionInfo(Object* name) {
 
 Object* Heap::AllocateConsString(String* first,
                                  String* second) {
-  StringShape first_shape(first);
-  StringShape second_shape(second);
-  int first_length = first->length(first_shape);
-  int second_length = second->length(second_shape);
+  int first_length = first->length();
+  int second_length = second->length();
   int length = first_length + second_length;
-  bool is_ascii = first_shape.IsAsciiRepresentation()
-      && second_shape.IsAsciiRepresentation();
+  bool is_ascii = StringShape(first).IsAsciiRepresentation()
+      && StringShape(second).IsAsciiRepresentation();
 
   // If the resulting string is small make a flat string.
   if (length < String::kMinNonFlatLength) {
-    ASSERT(first->IsFlat(first_shape));
-    ASSERT(second->IsFlat(second_shape));
+    ASSERT(first->IsFlat());
+    ASSERT(second->IsFlat());
     if (is_ascii) {
       Object* result = AllocateRawAsciiString(length);
       if (result->IsFailure()) return result;
       // Copy the characters into the new object.
       char* dest = SeqAsciiString::cast(result)->GetChars();
-      String::WriteToFlat(first, first_shape, dest, 0, first_length);
-      String::WriteToFlat(second,
-                          second_shape,
-                          dest + first_length,
-                          0,
-                          second_length);
+      String::WriteToFlat(first, dest, 0, first_length);
+      String::WriteToFlat(second, dest + first_length, 0, second_length);
       return result;
     } else {
       Object* result = AllocateRawTwoByteString(length);
       if (result->IsFailure()) return result;
       // Copy the characters into the new object.
       uc16* dest = SeqTwoByteString::cast(result)->GetChars();
-      String::WriteToFlat(first, first_shape, dest, 0, first_length);
-      String::WriteToFlat(second,
-                          second_shape,
-                          dest + first_length,
-                          0,
-                          second_length);
+      String::WriteToFlat(first, dest, 0, first_length);
+      String::WriteToFlat(second, dest + first_length, 0, second_length);
       return result;
     }
   }
@@ -1457,25 +1445,24 @@ Object* Heap::AllocateConsString(String* first,
 Object* Heap::AllocateSlicedString(String* buffer,
                                    int start,
                                    int end) {
-  StringShape buffer_shape(buffer);
   int length = end - start;
 
   // If the resulting string is small make a sub string.
   if (end - start <= String::kMinNonFlatLength) {
-    return Heap::AllocateSubString(buffer, buffer_shape, start, end);
+    return Heap::AllocateSubString(buffer, start, end);
   }
 
   Map* map;
   if (length <= String::kMaxShortStringSize) {
-    map = buffer_shape.IsAsciiRepresentation() ?
+    map = StringShape(buffer).IsAsciiRepresentation() ?
       short_sliced_ascii_string_map() :
       short_sliced_string_map();
   } else if (length <= String::kMaxMediumStringSize) {
-    map = buffer_shape.IsAsciiRepresentation() ?
+    map = StringShape(buffer).IsAsciiRepresentation() ?
       medium_sliced_ascii_string_map() :
       medium_sliced_string_map();
   } else {
-    map = buffer_shape.IsAsciiRepresentation() ?
+    map = StringShape(buffer).IsAsciiRepresentation() ?
       long_sliced_ascii_string_map() :
       long_sliced_string_map();
   }
@@ -1493,41 +1480,38 @@ Object* Heap::AllocateSlicedString(String* buffer,
 
 
 Object* Heap::AllocateSubString(String* buffer,
-                                StringShape buffer_shape,
                                 int start,
                                 int end) {
   int length = end - start;
 
   if (length == 1) {
     return Heap::LookupSingleCharacterStringFromCode(
-        buffer->Get(buffer_shape, start));
+        buffer->Get(start));
   }
 
   // Make an attempt to flatten the buffer to reduce access time.
-  if (!buffer->IsFlat(buffer_shape)) {
-    buffer->TryFlatten(buffer_shape);
-    buffer_shape = StringShape(buffer);
+  if (!buffer->IsFlat()) {
+    buffer->TryFlatten();
   }
 
-  Object* result = buffer_shape.IsAsciiRepresentation()
+  Object* result = StringShape(buffer).IsAsciiRepresentation()
       ? AllocateRawAsciiString(length)
       : AllocateRawTwoByteString(length);
   if (result->IsFailure()) return result;
 
   // Copy the characters into the new object.
   String* string_result = String::cast(result);
-  StringShape result_shape(string_result);
   StringHasher hasher(length);
   int i = 0;
   for (; i < length && hasher.is_array_index(); i++) {
-    uc32 c = buffer->Get(buffer_shape, start + i);
+    uc32 c = buffer->Get(start + i);
     hasher.AddCharacter(c);
-    string_result->Set(result_shape, i, c);
+    string_result->Set(i, c);
   }
   for (; i < length; i++) {
-    uc32 c = buffer->Get(buffer_shape, start + i);
+    uc32 c = buffer->Get(start + i);
     hasher.AddCharacterNoIndex(c);
-    string_result->Set(result_shape, i, c);
+    string_result->Set(i, c);
   }
   string_result->set_length_field(hasher.GetHashField());
   return result;
@@ -1590,7 +1574,7 @@ Object* Heap::LookupSingleCharacterStringFromCode(uint16_t code) {
   Object* result = Heap::AllocateRawTwoByteString(1);
   if (result->IsFailure()) return result;
   String* answer = String::cast(result);
-  answer->Set(StringShape(answer), 0, code);
+  answer->Set(0, code);
   return answer;
 }
 
@@ -2016,10 +2000,9 @@ Object* Heap::AllocateStringFromUtf8(Vector<const char> string,
   // Convert and copy the characters into the new object.
   String* string_result = String::cast(result);
   decoder->Reset(string.start(), string.length());
-  StringShape result_shape(string_result);
   for (int i = 0; i < chars; i++) {
     uc32 r = decoder->GetNext();
-    string_result->Set(result_shape, i, r);
+    string_result->Set(i, r);
   }
   return result;
 }
@@ -2042,9 +2025,8 @@ Object* Heap::AllocateStringFromTwoByte(Vector<const uc16> string,
   // Copy the characters into the new object, which may be either ASCII or
   // UTF-16.
   String* string_result = String::cast(result);
-  StringShape result_shape(string_result);
   for (int i = 0; i < string.length(); i++) {
-    string_result->Set(result_shape, i, string[i]);
+    string_result->Set(i, string[i]);
   }
   return result;
 }
@@ -2163,14 +2145,13 @@ Object* Heap::AllocateInternalSymbol(unibrow::CharacterStream* buffer,
   reinterpret_cast<HeapObject*>(result)->set_map(map);
   // The hash value contains the length of the string.
   String* answer = String::cast(result);
-  StringShape answer_shape(answer);
   answer->set_length_field(length_field);
 
   ASSERT_EQ(size, answer->Size());
 
   // Fill in the characters.
   for (int i = 0; i < chars; i++) {
-    answer->Set(answer_shape, i, buffer->GetNext());
+    answer->Set(i, buffer->GetNext());
   }
   return answer;
 }
index 5a09934..a13f027 100644 (file)
@@ -532,7 +532,6 @@ class Heap : public AllStatic {
   // failed.
   // Please note this does not perform a garbage collection.
   static Object* AllocateSubString(String* buffer,
-                                   StringShape buffer_shape,
                                    int start,
                                    int end);
 
index 33f6ec6..1cc5c5a 100644 (file)
@@ -569,13 +569,12 @@ bool IrregexpInterpreter::Match(Handle<ByteArray> code_array,
                                 Handle<String> subject,
                                 int* registers,
                                 int start_position) {
-  ASSERT(subject->IsFlat(StringShape(*subject)));
+  ASSERT(subject->IsFlat());
 
   AssertNoAllocation a;
   const byte* code_base = code_array->GetDataStartAddress();
-  StringShape subject_shape(*subject);
   uc16 previous_char = '\n';
-  if (subject_shape.IsAsciiRepresentation()) {
+  if (StringShape(*subject).IsAsciiRepresentation()) {
     Vector<const char> subject_vector = subject->ToAsciiVector();
     if (start_position != 0) previous_char = subject_vector[start_position - 1];
     return RawMatch(code_base,
index 147afd3..7acf639 100644 (file)
 namespace v8 { namespace internal {
 
 
-String* RegExpImpl::last_ascii_string_ = NULL;
-String* RegExpImpl::two_byte_cached_string_ = NULL;
-
-
-void RegExpImpl::NewSpaceCollectionPrologue() {
-  // The two byte string is always in the old space.  The Ascii string may be
-  // in either place.  If it is in the old space we don't need to do anything.
-  if (Heap::InNewSpace(last_ascii_string_)) {
-    // Invalidate the cache.
-    last_ascii_string_ = NULL;
-    two_byte_cached_string_ = NULL;
-  }
-}
-
-
-void RegExpImpl::OldSpaceCollectionPrologue() {
-  last_ascii_string_ = NULL;
-  two_byte_cached_string_ = NULL;
-}
-
-
 Handle<Object> RegExpImpl::CreateRegExpLiteral(Handle<JSFunction> constructor,
                                                Handle<String> pattern,
                                                Handle<String> flags,
@@ -92,55 +71,10 @@ Handle<Object> RegExpImpl::CreateRegExpLiteral(Handle<JSFunction> constructor,
 }
 
 
-// Converts a source string to a 16 bit flat string or a SlicedString containing
-// a 16 bit flat string).
-Handle<String> RegExpImpl::CachedStringToTwoByte(Handle<String> subject) {
-  if (*subject == last_ascii_string_) {
-    ASSERT(two_byte_cached_string_ != NULL);
-    return Handle<String>(String::cast(two_byte_cached_string_));
-  }
-  Handle<String> two_byte_string = StringToTwoByte(subject);
-  last_ascii_string_ = *subject;
-  two_byte_cached_string_ = *two_byte_string;
-  return two_byte_string;
-}
-
-
-// Converts a source string to a 16 bit flat string or a SlicedString containing
-// a 16 bit flat string).
-Handle<String> RegExpImpl::StringToTwoByte(Handle<String> pattern) {
-  StringShape shape(*pattern);
-  if (!pattern->IsFlat(shape)) {
-    FlattenString(pattern);
-    shape = StringShape(*pattern);
-  }
-  Handle<String> flat_string(shape.IsCons() ?
-    String::cast(ConsString::cast(*pattern)->first()) :
-    *pattern);
-  ASSERT(flat_string->IsString());
-  StringShape flat_shape(*flat_string);
-  ASSERT(!flat_shape.IsCons());
-  ASSERT(flat_shape.IsSequential() ||
-         flat_shape.IsSliced() ||
-         flat_shape.IsExternal());
-  if (!flat_shape.IsAsciiRepresentation()) {
-    return flat_string;
-  }
-
-  int len = flat_string->length(flat_shape);
-  Handle<String> two_byte_string =
-    Factory::NewRawTwoByteString(len, TENURED);
-  uc16* dest = SeqTwoByteString::cast(*two_byte_string)->GetChars();
-  String::WriteToFlat(*flat_string, flat_shape, dest, 0, len);
-  return two_byte_string;
-}
-
-
 static JSRegExp::Flags RegExpFlagsFromString(Handle<String> str) {
   int flags = JSRegExp::NONE;
-  StringShape shape(*str);
-  for (int i = 0; i < str->length(shape); i++) {
-    switch (str->Get(shape, i)) {
+  for (int i = 0; i < str->length(); i++) {
+    switch (str->Get(i)) {
       case 'i':
         flags |= JSRegExp::IGNORE_CASE;
         break;
@@ -421,7 +355,7 @@ bool RegExpImpl::EnsureCompiledIrregexp(Handle<JSRegExp> re,
   JSRegExp::Flags flags = re->GetFlags();
 
   Handle<String> pattern(re->Pattern());
-  if (!pattern->IsFlat(StringShape(*pattern))) {
+  if (!pattern->IsFlat()) {
     FlattenString(pattern);
   }
 
@@ -552,7 +486,7 @@ Handle<Object> RegExpImpl::IrregexpExec(Handle<JSRegExp> regexp,
   }
 #endif
 
-  if (!subject->IsFlat(StringShape(*subject))) {
+  if (!subject->IsFlat()) {
     FlattenString(subject);
   }
 
@@ -590,7 +524,7 @@ Handle<Object> RegExpImpl::IrregexpExecGlobal(Handle<JSRegExp> regexp,
   int result_length = 0;
   Handle<Object> matches;
 
-  if (!subject->IsFlat(StringShape(*subject))) {
+  if (!subject->IsFlat()) {
     FlattenString(subject);
   }
 
@@ -659,9 +593,8 @@ Handle<Object> RegExpImpl::IrregexpExecOnce(Handle<FixedArray> regexp,
                                             int previous_index,
                                             int* offsets_vector,
                                             int offsets_vector_length) {
-  StringShape shape(*subject);
-  ASSERT(subject->IsFlat(shape));
-  bool is_ascii = shape.IsAsciiRepresentation();
+  ASSERT(subject->IsFlat());
+  bool is_ascii = StringShape(*subject).IsAsciiRepresentation();
   bool rc;
 
   Handle<String> original_subject = subject;
index 145cb26..f6e2052 100644 (file)
@@ -108,15 +108,6 @@ class RegExpImpl {
                                            Handle<String> subject,
                                            Handle<JSArray> lastMatchInfo);
 
-  static void NewSpaceCollectionPrologue();
-  static void OldSpaceCollectionPrologue();
-
-  // Converts a source string to a 16 bit flat string.  The string
-  // will be either sequential or it will be a SlicedString backed
-  // by a flat string.
-  static Handle<String> StringToTwoByte(Handle<String> pattern);
-  static Handle<String> CachedStringToTwoByte(Handle<String> pattern);
-
   // Offsets in the lastMatchInfo array.
   static const int kLastCaptureCount = 0;
   static const int kLastSubject = 1;
index 805bb51..bb895e2 100644 (file)
@@ -362,29 +362,27 @@ void LogMessageBuilder::Append(const char c) {
 // Append a heap string.
 void LogMessageBuilder::Append(String* str) {
   AssertNoAllocation no_heap_allocation;  // Ensure string stay valid.
-  StringShape shape(str);
-  int length = str->length(shape);
+  int length = str->length();
   for (int i = 0; i < length; i++) {
-    Append(static_cast<char>(str->Get(shape, i)));
+    Append(static_cast<char>(str->Get(i)));
   }
 }
 
 void LogMessageBuilder::AppendDetailed(String* str, bool show_impl_info) {
   AssertNoAllocation no_heap_allocation;  // Ensure string stay valid.
-  StringShape shape(str);
-  int len = str->length(shape);
+  int len = str->length();
   if (len > 0x1000)
     len = 0x1000;
   if (show_impl_info) {
-    Append(shape.IsAsciiRepresentation() ? 'a' : '2');
-    if (shape.IsExternal())
+    Append(StringShape(str).IsAsciiRepresentation() ? 'a' : '2');
+    if (StringShape(str).IsExternal())
       Append('e');
-    if (shape.IsSymbol())
+    if (StringShape(str).IsSymbol())
       Append('#');
     Append(":%i:", str->length());
   }
   for (int i = 0; i < len; i++) {
-    uc32 c = str->Get(shape, i);
+    uc32 c = str->Get(i);
     if (c > 0xff) {
       Append("\\u%04x", c);
     } else if (c < 32 || c > 126) {
index de5b1dd..f40fd3e 100644 (file)
@@ -491,20 +491,19 @@ void JSValue::JSValueVerify() {
 
 
 void String::StringPrint() {
-  StringShape shape(this);
-  if (shape.IsSymbol()) {
+  if (StringShape(this).IsSymbol()) {
     PrintF("#");
-  } else if (shape.IsCons()) {
+  } else if (StringShape(this).IsCons()) {
     PrintF("c\"");
   } else {
     PrintF("\"");
   }
 
   for (int i = 0; i < length(); i++) {
-    PrintF("%c", Get(shape, i));
+    PrintF("%c", Get(i));
   }
 
-  if (!shape.IsSymbol()) PrintF("\"");
+  if (!StringShape(this).IsSymbol()) PrintF("\"");
 }
 
 
index af2f0f0..bfa92ee 100644 (file)
@@ -143,15 +143,15 @@ bool Object::IsSeqString() {
 
 bool Object::IsSeqAsciiString() {
   if (!IsString()) return false;
-  StringShape shape(String::cast(this));
-  return shape.IsSequential() && shape.IsAsciiRepresentation();
+  return StringShape(String::cast(this)).IsSequential() &&
+         StringShape(String::cast(this)).IsAsciiRepresentation();
 }
 
 
 bool Object::IsSeqTwoByteString() {
   if (!IsString()) return false;
-  StringShape shape(String::cast(this));
-  return shape.IsSequential() && shape.IsTwoByteRepresentation();
+  return StringShape(String::cast(this)).IsSequential() &&
+         StringShape(String::cast(this)).IsTwoByteRepresentation();
 }
 
 
@@ -163,15 +163,15 @@ bool Object::IsExternalString() {
 
 bool Object::IsExternalAsciiString() {
   if (!IsString()) return false;
-  StringShape shape(String::cast(this));
-  return shape.IsExternal() && shape.IsAsciiRepresentation();
+  return StringShape(String::cast(this)).IsExternal() &&
+         StringShape(String::cast(this)).IsAsciiRepresentation();
 }
 
 
 bool Object::IsExternalTwoByteString() {
   if (!IsString()) return false;
-  StringShape shape(String::cast(this));
-  return shape.IsExternal() && shape.IsTwoByteRepresentation();
+  return StringShape(String::cast(this)).IsExternal() &&
+         StringShape(String::cast(this)).IsTwoByteRepresentation();
 }
 
 
@@ -1243,15 +1243,13 @@ void DescriptorArray::fast_swap(FixedArray* array, int first, int second) {
 int DescriptorArray::Search(String* name) {
   SLOW_ASSERT(IsSortedNoDuplicates());
 
-  StringShape shape(name);
-
   // Check for empty descriptor array.
   int nof = number_of_descriptors();
   if (nof == 0) return kNotFound;
 
   // Fast case: do linear search for small arrays.
   const int kMaxElementsForLinearSearch = 8;
-  if (shape.IsSymbol() && nof < kMaxElementsForLinearSearch) {
+  if (StringShape(name).IsSymbol() && nof < kMaxElementsForLinearSearch) {
     return LinearSearch(name, nof);
   }
 
@@ -1392,27 +1390,21 @@ INT_ACCESSORS(Array, length, kLengthOffset)
 
 bool String::Equals(String* other) {
   if (other == this) return true;
-  StringShape this_shape(this);
-  StringShape other_shape(other);
-  if (this_shape.IsSymbol() && other_shape.IsSymbol()) return false;
-  return SlowEquals(this_shape, other, other_shape);
+  if (StringShape(this).IsSymbol() && StringShape(other).IsSymbol()) {
+    return false;
+  }
+  return SlowEquals(other);
 }
 
 
-int String::length(StringShape shape) {
-  ASSERT(shape.type() == StringShape(this).type());
+int String::length() {
   uint32_t len = READ_INT_FIELD(this, kLengthOffset);
 
   ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
   ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
   ASSERT(kLongStringTag == 0);
 
-  return len >> (shape.size_tag() + kLongLengthShift);
-}
-
-
-int String::length() {
-  return length(StringShape(this));
+  return len >> (StringShape(this).size_tag() + kLongLengthShift);
 }
 
 
@@ -1421,10 +1413,9 @@ void String::set_length(int value) {
   ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
   ASSERT(kLongStringTag == 0);
 
-  StringShape shape(this);
   WRITE_INT_FIELD(this,
                   kLengthOffset,
-                  value << (shape.size_tag() + kLongLengthShift));
+                  value << (StringShape(this).size_tag() + kLongLengthShift));
 }
 
 
@@ -1438,21 +1429,19 @@ void String::set_length_field(uint32_t value) {
 }
 
 
-Object* String::TryFlattenIfNotFlat(StringShape shape) {
-  ASSERT(shape.type() == StringShape(this).type());
+Object* String::TryFlattenIfNotFlat() {
   // We don't need to flatten strings that are already flat.  Since this code
   // is inlined, it can be helpful in the flat case to not call out to Flatten.
-  if (!IsFlat(shape)) {
-    return TryFlatten(shape);
+  if (!IsFlat()) {
+    return TryFlatten();
   }
   return this;
 }
 
 
-uint16_t String::Get(StringShape shape, int index) {
-  ASSERT(shape.type() == StringShape(this).type());
-  ASSERT(index >= 0 && index < length(shape));
-  switch (shape.full_representation_tag()) {
+uint16_t String::Get(int index) {
+  ASSERT(index >= 0 && index < length());
+  switch (StringShape(this).full_representation_tag()) {
     case kSeqStringTag | kAsciiStringTag:
       return SeqAsciiString::cast(this)->SeqAsciiStringGet(index);
     case kSeqStringTag | kTwoByteStringTag:
@@ -1476,29 +1465,26 @@ uint16_t String::Get(StringShape shape, int index) {
 }
 
 
-void String::Set(StringShape shape, int index, uint16_t value) {
-  ASSERT(shape.type() == StringShape(this).type());
-  ASSERT(shape.type() == StringShape(this).type());
-  ASSERT(index >= 0 && index < length(shape));
-  ASSERT(shape.IsSequential());
+void String::Set(int index, uint16_t value) {
+  ASSERT(index >= 0 && index < length());
+  ASSERT(StringShape(this).IsSequential());
 
-  return shape.IsAsciiRepresentation()
+  return StringShape(this).IsAsciiRepresentation()
       ? SeqAsciiString::cast(this)->SeqAsciiStringSet(index, value)
       : SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value);
 }
 
 
-bool String::IsFlat(StringShape shape) {
-  ASSERT(shape.type() == StringShape(this).type());
-  switch (shape.representation_tag()) {
+bool String::IsFlat() {
+  switch (StringShape(this).representation_tag()) {
     case kConsStringTag: {
       String* second = ConsString::cast(this)->second();
       // Only flattened strings have second part empty.
       return second->length() == 0;
     }
     case kSlicedStringTag: {
-      StringShape slice_shape = StringShape(SlicedString::cast(this)->buffer());
-      StringRepresentationTag tag = slice_shape.representation_tag();
+      StringRepresentationTag tag =
+          StringShape(SlicedString::cast(this)->buffer()).representation_tag();
       return tag == kSeqStringTag || tag == kExternalStringTag;
     }
     default:
@@ -1552,7 +1538,7 @@ void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) {
 }
 
 
-int SeqTwoByteString::SeqTwoByteStringSize(StringShape shape) {
+int SeqTwoByteString::SeqTwoByteStringSize(InstanceType instance_type) {
   uint32_t length = READ_INT_FIELD(this, kLengthOffset);
 
   ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
@@ -1561,13 +1547,13 @@ int SeqTwoByteString::SeqTwoByteStringSize(StringShape shape) {
 
   // Use the map (and not 'this') to compute the size tag, since
   // TwoByteStringSize is called during GC when maps are encoded.
-  length >>= shape.size_tag() + kLongLengthShift;
+  length >>= StringShape(instance_type).size_tag() + kLongLengthShift;
 
   return SizeFor(length);
 }
 
 
-int SeqAsciiString::SeqAsciiStringSize(StringShape shape) {
+int SeqAsciiString::SeqAsciiStringSize(InstanceType instance_type) {
   uint32_t length = READ_INT_FIELD(this, kLengthOffset);
 
   ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
@@ -1576,7 +1562,7 @@ int SeqAsciiString::SeqAsciiStringSize(StringShape shape) {
 
   // Use the map (and not 'this') to compute the size tag, since
   // AsciiStringSize is called during GC when maps are encoded.
-  length >>= shape.size_tag() + kLongLengthShift;
+  length >>= StringShape(instance_type).size_tag() + kLongLengthShift;
 
   return SizeFor(length);
 }
index 15ce483..42c9d2a 100644 (file)
@@ -575,10 +575,9 @@ Failure* Failure::RetryAfterGC(int requested_bytes, AllocationSpace space) {
 // We don't use the BBC's overcorrect "an historic occasion" though if
 // you speak a dialect you may well say "an 'istoric occasion".
 static bool AnWord(String* str) {
-  StringShape shape(str);
-  if (str->length(shape) == 0) return false;  // A nothing.
-  int c0 = str->Get(shape, 0);
-  int c1 = str->length(shape) > 1 ? str->Get(shape, 1) : 0;
+  if (str->length() == 0) return false;  // A nothing.
+  int c0 = str->Get(0);
+  int c1 = str->length() > 1 ? str->Get(1) : 0;
   if (c0 == 'U') {
     if (c1 > 'Z') {
       return true;  // An Umpire, but a UTF8String, a U.
@@ -594,7 +593,7 @@ static bool AnWord(String* str) {
 }
 
 
-Object* String::TryFlatten(StringShape shape) {
+Object* String::TryFlatten() {
 #ifdef DEBUG
   // Do not attempt to flatten in debug mode when allocation is not
   // allowed.  This is to avoid an assertion failure when allocating.
@@ -603,7 +602,7 @@ Object* String::TryFlatten(StringShape shape) {
   if (!Heap::IsAllocationAllowed()) return this;
 #endif
 
-  switch (shape.representation_tag()) {
+  switch (StringShape(this).representation_tag()) {
     case kSlicedStringTag: {
       SlicedString* ss = SlicedString::cast(this);
       // The SlicedString constructor should ensure that there are no
@@ -611,7 +610,7 @@ Object* String::TryFlatten(StringShape shape) {
       // SlicedStrings.
       String* buf = ss->buffer();
       ASSERT(!buf->IsSlicedString());
-      Object* ok = buf->TryFlatten(StringShape(buf));
+      Object* ok = buf->TryFlatten();
       if (ok->IsFailure()) return ok;
       // Under certain circumstances (TryFlattenIfNotFlat fails in
       // String::Slice) we can have a cons string under a slice.
@@ -630,21 +629,19 @@ Object* String::TryFlatten(StringShape shape) {
       // cons string is in old space.  It can never get GCed until there is
       // an old space GC.
       PretenureFlag tenure = Heap::InNewSpace(this) ? NOT_TENURED : TENURED;
-      int len = length(shape);
+      int len = length();
       Object* object;
       String* result;
-      if (shape.IsAsciiRepresentation()) {
+      if (StringShape(this).IsAsciiRepresentation()) {
         object = Heap::AllocateRawAsciiString(len, tenure);
         if (object->IsFailure()) return object;
         result = String::cast(object);
         String* first = cs->first();
-        StringShape first_shape(first);
-        int first_length = first->length(first_shape);
+        int first_length = first->length();
         char* dest = SeqAsciiString::cast(result)->GetChars();
-        WriteToFlat(first, first_shape, dest, 0, first_length);
+        WriteToFlat(first, dest, 0, first_length);
         String* second = cs->second();
         WriteToFlat(second,
-                    StringShape(second),
                     dest + first_length,
                     0,
                     len - first_length);
@@ -654,12 +651,10 @@ Object* String::TryFlatten(StringShape shape) {
         result = String::cast(object);
         uc16* dest = SeqTwoByteString::cast(result)->GetChars();
         String* first = cs->first();
-        StringShape first_shape(first);
-        int first_length = first->length(first_shape);
-        WriteToFlat(first, first_shape, dest, 0, first_length);
+        int first_length = first->length();
+        WriteToFlat(first, dest, 0, first_length);
         String* second = cs->second();
         WriteToFlat(second,
-                    StringShape(second),
                     dest + first_length,
                     0,
                     len - first_length);
@@ -761,8 +756,7 @@ bool String::MakeExternal(v8::String::ExternalAsciiStringResource* resource) {
 
 
 void String::StringShortPrint(StringStream* accumulator) {
-  StringShape shape(this);
-  int len = length(shape);
+  int len = length();
   if (len > kMaxMediumStringSize) {
     accumulator->Add("<Very long string[%u]>", len);
     return;
@@ -790,7 +784,7 @@ void String::StringShortPrint(StringStream* accumulator) {
   }
   buf.Reset(this);
   if (ascii) {
-    accumulator->Add("<String[%u]: ", length(shape));
+    accumulator->Add("<String[%u]: ", length());
     for (int i = 0; i < len; i++) {
       accumulator->Put(buf.GetNext());
     }
@@ -798,7 +792,7 @@ void String::StringShortPrint(StringStream* accumulator) {
   } else {
     // Backslash indicates that the string contains control
     // characters and that backslashes are therefore escaped.
-    accumulator->Add("<String[%u]\\: ", length(shape));
+    accumulator->Add("<String[%u]\\: ", length());
     for (int i = 0; i < len; i++) {
       int c = buf.GetNext();
       if (c == '\n') {
@@ -979,12 +973,12 @@ int HeapObject::SlowSizeFromMap(Map* map) {
 
   if (instance_type < FIRST_NONSTRING_TYPE
       && (StringShape(instance_type).IsSequential())) {
-    StringShape shape(instance_type);
-    if (shape.IsAsciiRepresentation()) {
-      return reinterpret_cast<SeqAsciiString*>(this)->SeqAsciiStringSize(shape);
+    if (StringShape(instance_type).IsAsciiRepresentation()) {
+      SeqAsciiString* seq_ascii_this = reinterpret_cast<SeqAsciiString*>(this);
+      return seq_ascii_this->SeqAsciiStringSize(instance_type);
     } else {
       SeqTwoByteString* self = reinterpret_cast<SeqTwoByteString*>(this);
-      return self->SeqTwoByteStringSize(shape);
+      return self->SeqTwoByteStringSize(instance_type);
     }
   }
 
@@ -2559,7 +2553,7 @@ Object* JSObject::DefineGetterSetter(String* name,
   }
 
   // Try to flatten before operating on the string.
-  name->TryFlattenIfNotFlat(StringShape(name));
+  name->TryFlattenIfNotFlat();
 
   // Check if there is an API defined callback object which prohibits
   // callback overwriting in this object or it's prototype chain.
@@ -3274,13 +3268,12 @@ bool String::LooksValid() {
 
 
 int String::Utf8Length() {
-  StringShape shape(this);
-  if (shape.IsAsciiRepresentation()) return length(shape);
+  if (StringShape(this).IsAsciiRepresentation()) return length();
   // Attempt to flatten before accessing the string.  It probably
   // doesn't make Utf8Length faster, but it is very likely that
   // the string will be accessed later (for example by WriteUtf8)
   // so it's still a good idea.
-  TryFlattenIfNotFlat(shape);  // shape is now no longer valid.
+  TryFlattenIfNotFlat();
   Access<StringInputBuffer> buffer(&string_input_buffer);
   buffer->Reset(0, this);
   int result = 0;
@@ -3291,26 +3284,23 @@ int String::Utf8Length() {
 
 
 Vector<const char> String::ToAsciiVector() {
-  StringShape shape(this);
-  ASSERT(shape.IsAsciiRepresentation());
-  ASSERT(IsFlat(shape));
+  ASSERT(StringShape(this).IsAsciiRepresentation());
+  ASSERT(IsFlat());
 
   int offset = 0;
-  int length = this->length(shape);
-  StringRepresentationTag string_tag = shape.representation_tag();
+  int length = this->length();
+  StringRepresentationTag string_tag = StringShape(this).representation_tag();
   String* string = this;
   if (string_tag == kSlicedStringTag) {
     SlicedString* sliced = SlicedString::cast(string);
     offset += sliced->start();
     string = sliced->buffer();
-    shape = StringShape(string);
-    string_tag = shape.representation_tag();
+    string_tag = StringShape(string).representation_tag();
   } else if (string_tag == kConsStringTag) {
     ConsString* cons = ConsString::cast(string);
-    ASSERT(cons->second()->length(StringShape(cons->second())) == 0);
+    ASSERT(cons->second()->length() == 0);
     string = cons->first();
-    shape = StringShape(string);
-    string_tag = shape.representation_tag();
+    string_tag = StringShape(string).representation_tag();
   }
   if (string_tag == kSeqStringTag) {
     SeqAsciiString* seq = SeqAsciiString::cast(string);
@@ -3325,26 +3315,23 @@ Vector<const char> String::ToAsciiVector() {
 
 
 Vector<const uc16> String::ToUC16Vector() {
-  StringShape shape(this);
-  ASSERT(shape.IsTwoByteRepresentation());
-  ASSERT(IsFlat(shape));
+  ASSERT(StringShape(this).IsTwoByteRepresentation());
+  ASSERT(IsFlat());
 
   int offset = 0;
-  int length = this->length(shape);
-  StringRepresentationTag string_tag = shape.representation_tag();
+  int length = this->length();
+  StringRepresentationTag string_tag = StringShape(this).representation_tag();
   String* string = this;
   if (string_tag == kSlicedStringTag) {
     SlicedString* sliced = SlicedString::cast(string);
     offset += sliced->start();
     string = String::cast(sliced->buffer());
-    shape = StringShape(string);
-    string_tag = shape.representation_tag();
+    string_tag = StringShape(string).representation_tag();
   } else if (string_tag == kConsStringTag) {
     ConsString* cons = ConsString::cast(string);
-    ASSERT(cons->second()->length(StringShape(cons->second())) == 0);
+    ASSERT(cons->second()->length() == 0);
     string = cons->first();
-    shape = StringShape(string);
-    string_tag = shape.representation_tag();
+    string_tag = StringShape(string).representation_tag();
   }
   if (string_tag == kSeqStringTag) {
     SeqTwoByteString* seq = SeqTwoByteString::cast(string);
@@ -3424,9 +3411,8 @@ const uc16* String::GetTwoByteData() {
 
 
 const uc16* String::GetTwoByteData(unsigned start) {
-  StringShape shape(this);
-  ASSERT(!shape.IsAsciiRepresentation());
-  switch (shape.representation_tag()) {
+  ASSERT(!StringShape(this).IsAsciiRepresentation());
+  switch (StringShape(this).representation_tag()) {
     case kSeqStringTag:
       return SeqTwoByteString::cast(this)->SeqTwoByteStringGetData(start);
     case kExternalStringTag:
@@ -3438,7 +3424,7 @@ const uc16* String::GetTwoByteData(unsigned start) {
       if (StringShape(buffer).IsCons()) {
         ConsString* cs = ConsString::cast(buffer);
         // Flattened string.
-        ASSERT(cs->second()->length(StringShape(cs->second())) == 0);
+        ASSERT(cs->second()->length() == 0);
         buffer = cs->first();
       }
       return buffer->GetTwoByteData(start + sliced_string->start());
@@ -3541,8 +3527,7 @@ const unibrow::byte* ConsString::ConsStringReadBlock(ReadBlockBuffer* rbb,
 
   while (true) {
     String* left = current->first();
-    StringShape left_shape(left);
-    unsigned left_length = (unsigned)left->length(left_shape);
+    unsigned left_length = (unsigned)left->length();
     if (left_length > offset &&
         (max_chars <= left_length - offset ||
          (rbb->capacity <= left_length - offset &&
@@ -3554,7 +3539,7 @@ const unibrow::byte* ConsString::ConsStringReadBlock(ReadBlockBuffer* rbb,
       // the point where we switch to the -IntoBuffer routines (below) in order
       // to maximize the chances of delegating a big chunk of work to the
       // efficient *AsciiStringReadBlock routines.
-      if (left_shape.IsCons()) {
+      if (StringShape(left).IsCons()) {
         current = ConsString::cast(left);
         continue;
       } else {
@@ -3719,10 +3704,9 @@ const unibrow::byte* String::ReadBlock(String* input,
     rbb->remaining = 0;
     return NULL;
   }
-  StringShape shape(input);
-  switch (shape.representation_tag()) {
+  switch (StringShape(input).representation_tag()) {
     case kSeqStringTag:
-      if (shape.IsAsciiRepresentation()) {
+      if (StringShape(input).IsAsciiRepresentation()) {
         SeqAsciiString* str = SeqAsciiString::cast(input);
         return str->SeqAsciiStringReadBlock(&rbb->remaining,
                                             offset_ptr,
@@ -3743,7 +3727,7 @@ const unibrow::byte* String::ReadBlock(String* input,
                                                               offset_ptr,
                                                               max_chars);
     case kExternalStringTag:
-      if (shape.IsAsciiRepresentation()) {
+      if (StringShape(input).IsAsciiRepresentation()) {
         return ExternalAsciiString::cast(input)->ExternalAsciiStringReadBlock(
             &rbb->remaining,
             offset_ptr,
@@ -3795,9 +3779,8 @@ FlatStringReader::~FlatStringReader() {
 void FlatStringReader::RefreshState() {
   if (str_ == NULL) return;
   Handle<String> str(str_);
-  StringShape shape(*str);
-  ASSERT(str->IsFlat(shape));
-  is_ascii_ = shape.IsAsciiRepresentation();
+  ASSERT(str->IsFlat());
+  is_ascii_ = StringShape(*str).IsAsciiRepresentation();
   if (is_ascii_) {
     start_ = str->ToAsciiVector().start();
   } else {
@@ -3833,13 +3816,12 @@ void String::ReadBlockIntoBuffer(String* input,
                                  ReadBlockBuffer* rbb,
                                  unsigned* offset_ptr,
                                  unsigned max_chars) {
-  StringShape shape(input);
-  ASSERT(*offset_ptr <= (unsigned)input->length(shape));
+  ASSERT(*offset_ptr <= (unsigned)input->length());
   if (max_chars == 0) return;
 
-  switch (shape.representation_tag()) {
+  switch (StringShape(input).representation_tag()) {
     case kSeqStringTag:
-      if (shape.IsAsciiRepresentation()) {
+      if (StringShape(input).IsAsciiRepresentation()) {
         SeqAsciiString::cast(input)->SeqAsciiStringReadBlockIntoBuffer(rbb,
                                                                  offset_ptr,
                                                                  max_chars);
@@ -3861,7 +3843,7 @@ void String::ReadBlockIntoBuffer(String* input,
                                                                  max_chars);
       return;
     case kExternalStringTag:
-      if (shape.IsAsciiRepresentation()) {
+      if (StringShape(input).IsAsciiRepresentation()) {
          ExternalAsciiString::cast(input)->
              ExternalAsciiStringReadBlockIntoBuffer(rbb, offset_ptr, max_chars);
        } else {
@@ -3885,12 +3867,11 @@ const unibrow::byte* String::ReadBlock(String* input,
                                        unsigned capacity,
                                        unsigned* remaining,
                                        unsigned* offset_ptr) {
-  StringShape shape(input);
-  ASSERT(*offset_ptr <= (unsigned)input->length(shape));
-  unsigned chars = input->length(shape) - *offset_ptr;
+  ASSERT(*offset_ptr <= (unsigned)input->length());
+  unsigned chars = input->length() - *offset_ptr;
   ReadBlockBuffer rbb(util_buffer, 0, capacity, 0);
   const unibrow::byte* answer = ReadBlock(input, &rbb, offset_ptr, chars);
-  ASSERT(rbb.remaining <= static_cast<unsigned>(input->length(shape)));
+  ASSERT(rbb.remaining <= static_cast<unsigned>(input->length()));
   *remaining = rbb.remaining;
   return answer;
 }
@@ -3901,14 +3882,13 @@ const unibrow::byte* String::ReadBlock(String** raw_input,
                                        unsigned capacity,
                                        unsigned* remaining,
                                        unsigned* offset_ptr) {
-  StringShape shape(*raw_input);
   Handle<String> input(raw_input);
-  ASSERT(*offset_ptr <= (unsigned)input->length(shape));
-  unsigned chars = input->length(shape) - *offset_ptr;
+  ASSERT(*offset_ptr <= (unsigned)input->length());
+  unsigned chars = input->length() - *offset_ptr;
   if (chars > capacity) chars = capacity;
   ReadBlockBuffer rbb(util_buffer, 0, capacity, 0);
   ReadBlockIntoBuffer(*input, &rbb, offset_ptr, chars);
-  ASSERT(rbb.remaining <= static_cast<unsigned>(input->length(shape)));
+  ASSERT(rbb.remaining <= static_cast<unsigned>(input->length()));
   *remaining = rbb.remaining;
   return rbb.util_buffer;
 }
@@ -3928,13 +3908,12 @@ void ConsString::ConsStringReadBlockIntoBuffer(ReadBlockBuffer* rbb,
 
   while (true) {
     String* left = current->first();
-    StringShape left_shape(left);
-    unsigned left_length = (unsigned)left->length(left_shape);
+    unsigned left_length = (unsigned)left->length();
     if (left_length > offset &&
       max_chars <= left_length - offset) {
       // Left hand side only - iterate unless we have reached the bottom of
       // the cons tree.
-      if (left_shape.IsCons()) {
+      if (StringShape(left).IsCons()) {
         current = ConsString::cast(left);
         continue;
       } else {
@@ -4002,27 +3981,23 @@ uint16_t ConsString::ConsStringGet(int index) {
   // Check for a flattened cons string
   if (second()->length() == 0) {
     String* left = first();
-    return left->Get(StringShape(left), index);
+    return left->Get(index);
   }
 
   String* string = String::cast(this);
-  StringShape shape(string);
 
   while (true) {
-    if (shape.IsCons()) {
+    if (StringShape(string).IsCons()) {
       ConsString* cons_string = ConsString::cast(string);
       String* left = cons_string->first();
-      StringShape left_shape(left);
-      if (left->length(left_shape) > index) {
+      if (left->length() > index) {
         string = left;
-        shape = left_shape;
       } else {
-        index -= left->length(left_shape);
+        index -= left->length();
         string = cons_string->second();
-        shape = StringShape(string);
       }
     } else {
-      return string->Get(shape, index);
+      return string->Get(index);
     }
   }
 
@@ -4033,17 +4008,15 @@ uint16_t ConsString::ConsStringGet(int index) {
 
 template <typename sinkchar>
 void String::WriteToFlat(String* src,
-                         StringShape src_shape,
                          sinkchar* sink,
                          int f,
                          int t) {
   String* source = src;
-  StringShape shape = src_shape;
   int from = f;
   int to = t;
   while (true) {
-    ASSERT(0 <= from && from <= to && to <= source->length(shape));
-    switch (shape.full_representation_tag()) {
+    ASSERT(0 <= from && from <= to && to <= source->length());
+    switch (StringShape(source).full_representation_tag()) {
       case kAsciiStringTag | kExternalStringTag: {
         CopyChars(sink,
                   ExternalAsciiString::cast(source)->resource()->data() + from,
@@ -4077,19 +4050,17 @@ void String::WriteToFlat(String* src,
         from += start;
         to += start;
         source = String::cast(sliced_string->buffer());
-        shape = StringShape(source);
         break;
       }
       case kAsciiStringTag | kConsStringTag:
       case kTwoByteStringTag | kConsStringTag: {
         ConsString* cons_string = ConsString::cast(source);
         String* first = cons_string->first();
-        StringShape first_shape(first);
-        int boundary = first->length(first_shape);
+        int boundary = first->length();
         if (to - boundary >= boundary - from) {
           // Right hand side is longer.  Recurse over left.
           if (from < boundary) {
-            WriteToFlat(first, first_shape, sink, from, boundary);
+            WriteToFlat(first, sink, from, boundary);
             sink += boundary - from;
             from = 0;
           } else {
@@ -4097,20 +4068,17 @@ void String::WriteToFlat(String* src,
           }
           to -= boundary;
           source = cons_string->second();
-          shape = StringShape(source);
         } else {
           // Left hand side is longer.  Recurse over right.
           if (to > boundary) {
             String* second = cons_string->second();
             WriteToFlat(second,
-                        StringShape(second),
                         sink + boundary - from,
                         0,
                         to - boundary);
             to = boundary;
           }
           source = first;
-          shape = first_shape;
         }
         break;
       }
@@ -4128,7 +4096,7 @@ uint16_t SlicedString::SlicedStringGet(int index) {
   ASSERT(index >= 0 && index < this->length());
   // Delegate to the buffer string.
   String* underlying = buffer();
-  return underlying->Get(StringShape(underlying), start() + index);
+  return underlying->Get(start() + index);
 }
 
 
@@ -4192,9 +4160,8 @@ static StringInputBuffer string_compare_buffer_b;
 
 template <typename IteratorA>
 static inline bool CompareStringContentsPartial(IteratorA* ia, String* b) {
-  StringShape b_shape(b);
-  if (b->IsFlat(b_shape)) {
-    if (b_shape.IsAsciiRepresentation()) {
+  if (b->IsFlat()) {
+    if (StringShape(b).IsAsciiRepresentation()) {
       VectorIterator<char> ib(b->ToAsciiVector());
       return CompareStringContents(ia, &ib);
     } else {
@@ -4211,12 +4178,10 @@ static inline bool CompareStringContentsPartial(IteratorA* ia, String* b) {
 static StringInputBuffer string_compare_buffer_a;
 
 
-bool String::SlowEquals(StringShape this_shape,
-                        String* other,
-                        StringShape other_shape) {
+bool String::SlowEquals(String* other) {
   // Fast check: negative check with lengths.
-  int len = length(this_shape);
-  if (len != other->length(other_shape)) return false;
+  int len = length();
+  if (len != other->length()) return false;
   if (len == 0) return true;
 
   // Fast check: if hash code is computed for both strings
@@ -4225,18 +4190,18 @@ bool String::SlowEquals(StringShape this_shape,
     if (Hash() != other->Hash()) return false;
   }
 
-  if (this_shape.IsSequentialAscii() && other_shape.IsSequentialAscii()) {
+  if (StringShape(this).IsSequentialAscii() && StringShape(other).IsSequentialAscii()) {
     const char* str1 = SeqAsciiString::cast(this)->GetChars();
     const char* str2 = SeqAsciiString::cast(other)->GetChars();
     return CompareRawStringContents(Vector<const char>(str1, len),
                                     Vector<const char>(str2, len));
   }
 
-  if (this->IsFlat(this_shape)) {
-    if (this_shape.IsAsciiRepresentation()) {
+  if (this->IsFlat()) {
+    if (StringShape(this).IsAsciiRepresentation()) {
       Vector<const char> vec1 = this->ToAsciiVector();
-      if (other->IsFlat(other_shape)) {
-        if (other_shape.IsAsciiRepresentation()) {
+      if (other->IsFlat()) {
+        if (StringShape(other).IsAsciiRepresentation()) {
           Vector<const char> vec2 = other->ToAsciiVector();
           return CompareRawStringContents(vec1, vec2);
         } else {
@@ -4251,8 +4216,8 @@ bool String::SlowEquals(StringShape this_shape,
       }
     } else {
       Vector<const uc16> vec1 = this->ToUC16Vector();
-      if (other->IsFlat(other_shape)) {
-        if (other_shape.IsAsciiRepresentation()) {
+      if (other->IsFlat()) {
+        if (StringShape(other).IsAsciiRepresentation()) {
           VectorIterator<uc16> buf1(vec1);
           VectorIterator<char> ib(other->ToAsciiVector());
           return CompareStringContents(&buf1, &ib);
@@ -4302,14 +4267,13 @@ bool String::MarkAsUndetectable() {
 
 
 bool String::IsEqualTo(Vector<const char> str) {
-  StringShape this_shape(this);
-  int slen = length(this_shape);
+  int slen = length();
   Access<Scanner::Utf8Decoder> decoder(Scanner::utf8_decoder());
   decoder->Reset(str.start(), str.length());
   int i;
   for (i = 0; i < slen && decoder->has_more(); i++) {
     uc32 r = decoder->GetNext();
-    if (Get(this_shape, i) != r) return false;
+    if (Get(i) != r) return false;
   }
   return i == slen && !decoder->has_more();
 }
@@ -4363,8 +4327,7 @@ bool String::ComputeArrayIndex(unibrow::CharacterStream* buffer,
 
 
 bool String::SlowAsArrayIndex(uint32_t* index) {
-  StringShape shape(this);
-  if (length(shape) <= kMaxCachedArrayIndexLength) {
+  if (length() <= kMaxCachedArrayIndexLength) {
     Hash();  // force computation of hash code
     uint32_t field = length_field();
     if ((field & kIsArrayIndexMask) == 0) return false;
@@ -4372,7 +4335,7 @@ bool String::SlowAsArrayIndex(uint32_t* index) {
     return true;
   } else {
     StringInputBuffer buffer(this);
-    return ComputeArrayIndex(&buffer, index, length(shape));
+    return ComputeArrayIndex(&buffer, index, length());
   }
 }
 
@@ -4433,9 +4396,8 @@ uint32_t String::ComputeLengthAndHashField(unibrow::CharacterStream* buffer,
 
 
 Object* String::Slice(int start, int end) {
-  StringShape shape(this);
-  if (start == 0 && end == length(shape)) return this;
-  if (shape.representation_tag() == kSlicedStringTag) {
+  if (start == 0 && end == length()) return this;
+  if (StringShape(this).representation_tag() == kSlicedStringTag) {
     // Translate slices of a SlicedString into slices of the
     // underlying string buffer.
     SlicedString* str = SlicedString::cast(this);
@@ -4459,14 +4421,13 @@ Object* String::Slice(int start, int end) {
   // if Heap::AllocateSlicedString actually returned a SlicedString.  It will
   // return flat strings for small slices for efficiency reasons.
   String* answer = String::cast(result);
-  StringShape answer_shape(answer);
-  if (answer_shape.IsSliced() &&
-      shape.representation_tag() == kConsStringTag) {
-    TryFlatten(shape);
+  if (StringShape(answer).IsSliced() &&
+      StringShape(this).representation_tag() == kConsStringTag) {
+    TryFlatten();
     // If the flatten succeeded we might as well make the sliced string point
     // to the flat string rather than the cons string.
     String* second = ConsString::cast(this)->second();
-    if (second->length(StringShape(second)) == 0) {
+    if (second->length() == 0) {
       SlicedString::cast(answer)->set_buffer(ConsString::cast(this)->first());
     }
   }
@@ -4475,10 +4436,9 @@ Object* String::Slice(int start, int end) {
 
 
 void String::PrintOn(FILE* file) {
-  StringShape shape(this);
-  int length = this->length(shape);
+  int length = this->length();
   for (int i = 0; i < length; i++) {
-    fprintf(file, "%c", Get(shape, i));
+    fprintf(file, "%c", Get(i));
   }
 }
 
@@ -6034,13 +5994,12 @@ int JSObject::GetLocalElementKeys(FixedArray* storage,
     Object* val = JSValue::cast(this)->value();
     if (val->IsString()) {
       String* str = String::cast(val);
-      StringShape shape(str);
       if (storage) {
-        for (int i = 0; i < str->length(shape); i++) {
+        for (int i = 0; i < str->length(); i++) {
           storage->set(counter + i, Smi::FromInt(i), SKIP_WRITE_BARRIER);
         }
       }
-      counter += str->length(shape);
+      counter += str->length();
     }
   }
   ASSERT(!storage || storage->length() == counter);
@@ -6288,10 +6247,9 @@ class SymbolKey : public HashTableKey {
   Object* GetObject() {
     // If the string is a cons string, attempt to flatten it so that
     // symbols will most often be flat strings.
-    StringShape shape(string_);
-    if (shape.IsCons()) {
+    if (StringShape(string_).IsCons()) {
       ConsString* cons_string = ConsString::cast(string_);
-      cons_string->TryFlatten(shape);
+      cons_string->TryFlatten();
       if (cons_string->second() == Heap::empty_string()) {
         string_ = cons_string->first();
       }
index e6be74b..d43d616 100644 (file)
@@ -3139,13 +3139,9 @@ class StringHasher {
 // to be passed by value and is immutable, but be aware that flattening a
 // string can potentially alter its shape.  Also be aware that a GC caused by
 // something else can alter the shape of a string due to ConsString
-// shortcutting.
-//
-// Most of the methods designed to interrogate a string as to its exact nature
-// have been made into methods on StringShape in order to encourage the use of
-// StringShape.  The String class has both a length() and a length(StringShape)
-// operation.  The former is simpler to type, but the latter is faster if you
-// need the StringShape for some other operation immediately before or after.
+// shortcutting.  Keeping these restrictions in mind has proven to be error-
+// prone and so we no longer put StringShapes in variables unless there is a
+// concrete performance benefit at that particular point in the code.
 class StringShape BASE_EMBEDDED {
  public:
   inline explicit StringShape(String* s);
@@ -3194,9 +3190,6 @@ class StringShape BASE_EMBEDDED {
 class String: public HeapObject {
  public:
   // Get and set the length of the string.
-  // Fast version.
-  inline int length(StringShape shape);
-  // Easy version.
   inline int length();
   inline void set_length(int value);
 
@@ -3208,22 +3201,22 @@ class String: public HeapObject {
   inline void set_length_field(uint32_t value);
 
   // Get and set individual two byte chars in the string.
-  inline void Set(StringShape shape, int index, uint16_t value);
+  inline void Set(int index, uint16_t value);
   // Get individual two byte char in the string.  Repeated calls
   // to this method are not efficient unless the string is flat.
-  inline uint16_t Get(StringShape shape, int index);
+  inline uint16_t Get(int index);
 
   // Try to flatten the top level ConsString that is hiding behind this
   // string.  This is a no-op unless the string is a ConsString or a
   // SlicedString.  Flatten mutates the ConsString and might return a
   // failure.
-  Object* TryFlatten(StringShape shape);
+  Object* TryFlatten();
 
   // Try to flatten the string.  Checks first inline to see if it is necessary.
   // Do not handle allocation failures.  After calling TryFlattenIfNotFlat, the
   // string could still be a ConsString, in which case a failure is returned.
   // Use FlattenString from Handles.cc to be sure to flatten.
-  inline Object* TryFlattenIfNotFlat(StringShape shape);
+  inline Object* TryFlattenIfNotFlat();
 
   Vector<const char> ToAsciiVector();
   Vector<const uc16> ToUC16Vector();
@@ -3302,7 +3295,7 @@ class String: public HeapObject {
   void StringPrint();
   void StringVerify();
 #endif
-  inline bool IsFlat(StringShape shape);
+  inline bool IsFlat();
 
   // Layout description.
   static const int kLengthOffset = HeapObject::kHeaderSize;
@@ -3364,7 +3357,6 @@ class String: public HeapObject {
   // Helper function for flattening strings.
   template <typename sinkchar>
   static void WriteToFlat(String* source,
-                          StringShape shape,
                           sinkchar* sink,
                           int from,
                           int to);
@@ -3405,9 +3397,7 @@ class String: public HeapObject {
  private:
   // Slow case of String::Equals.  This implementation works on any strings
   // but it is most efficient on strings that are almost flat.
-  bool SlowEquals(StringShape this_shape,
-                  String* other,
-                  StringShape other_shape);
+  bool SlowEquals(String* other);
 
   // Slow case of AsArrayIndex.
   bool SlowAsArrayIndex(uint32_t* index);
@@ -3454,7 +3444,7 @@ class SeqAsciiString: public SeqString {
   // Garbage collection support.  This method is called by the
   // garbage collector to compute the actual size of an AsciiString
   // instance.
-  inline int SeqAsciiStringSize(StringShape shape);
+  inline int SeqAsciiStringSize(InstanceType instance_type);
 
   // Computes the size for an AsciiString instance of a given length.
   static int SizeFor(int length) {
@@ -3499,7 +3489,7 @@ class SeqTwoByteString: public SeqString {
   // Garbage collection support.  This method is called by the
   // garbage collector to compute the actual size of a TwoByteString
   // instance.
-  inline int SeqTwoByteStringSize(StringShape shape);
+  inline int SeqTwoByteStringSize(InstanceType instance_type);
 
   // Computes the size for a TwoByteString instance of a given length.
   static int SizeFor(int length) {
index 973a7fc..a760772 100644 (file)
@@ -1097,11 +1097,10 @@ FunctionLiteral* Parser::ParseProgram(Handle<String> source,
   ZoneScope zone_scope(DONT_DELETE_ON_EXIT);
 
   HistogramTimerScope timer(&Counters::parse);
-  StringShape shape(*source);
-  Counters::total_parse_size.Increment(source->length(shape));
+  Counters::total_parse_size.Increment(source->length());
 
   // Initialize parser state.
-  source->TryFlattenIfNotFlat(shape);
+  source->TryFlattenIfNotFlat();
   scanner_.Init(source, stream, 0);
   ASSERT(target_stack_ == NULL);
 
@@ -1150,9 +1149,8 @@ FunctionLiteral* Parser::ParseLazy(Handle<String> source,
                                    bool is_expression) {
   ZoneScope zone_scope(DONT_DELETE_ON_EXIT);
   HistogramTimerScope timer(&Counters::parse_lazy);
-  source->TryFlattenIfNotFlat(StringShape(*source));
-  StringShape shape(*source);
-  Counters::total_parse_size.Increment(source->length(shape));
+  source->TryFlattenIfNotFlat();
+  Counters::total_parse_size.Increment(source->length());
   SafeStringInputBuffer buffer(source.location());
 
   // Initialize parser state.
index c3bf531..0a1a169 100644 (file)
@@ -517,10 +517,9 @@ void PrettyPrinter::PrintLiteral(Handle<Object> value, bool quote) {
   Object* object = *value;
   if (object->IsString()) {
     String* string = String::cast(object);
-    StringShape shape(string);
     if (quote) Print("\"");
-    for (int i = 0; i < string->length(shape); i++) {
-      Print("%c", string->Get(shape, i));
+    for (int i = 0; i < string->length(); i++) {
+      Print("%c", string->Get(i));
     }
     if (quote) Print("\"");
   } else if (object == Heap::null_value()) {
index 0315586..e6e0716 100644 (file)
@@ -985,16 +985,14 @@ RegExpMacroAssemblerIA32::Result RegExpMacroAssemblerIA32::Match(
     int* offsets_vector,
     int offsets_vector_length,
     int previous_index) {
-  StringShape shape(*subject);
-
   // Character offsets into string.
   int start_offset = previous_index;
-  int end_offset = subject->length(shape);
+  int end_offset = subject->length();
 
-  if (shape.IsCons()) {
+  if (StringShape(*subject).IsCons()) {
     subject =
       Handle<String>(String::cast(ConsString::cast(*subject)->first()));
-  } else if (shape.IsSliced()) {
+  } else if (StringShape(*subject).IsSliced()) {
     SlicedString* slice = SlicedString::cast(*subject);
     start_offset += slice->start();
     end_offset += slice->start();
@@ -1002,13 +1000,12 @@ RegExpMacroAssemblerIA32::Result RegExpMacroAssemblerIA32::Match(
   }
 
   // String is now either Sequential or External
-  StringShape flatshape(*subject);
-  bool is_ascii = flatshape.IsAsciiRepresentation();
+  bool is_ascii = StringShape(*subject).IsAsciiRepresentation();
   int char_size_shift = is_ascii ? 0 : 1;
 
   RegExpMacroAssemblerIA32::Result res;
 
-  if (flatshape.IsExternal()) {
+  if (StringShape(*subject).IsExternal()) {
     const byte* address;
     if (is_ascii) {
       ExternalAsciiString* ext = ExternalAsciiString::cast(*subject);
index 51dc24e..0705e2c 100644 (file)
@@ -1077,12 +1077,11 @@ static Object* CharCodeAt(String* subject, Object* index) {
   // Flatten the string.  If someone wants to get a char at an index
   // in a cons string, it is likely that more indices will be
   // accessed.
-  subject->TryFlattenIfNotFlat(StringShape(subject));
-  StringShape shape(subject);
-  if (i >= static_cast<uint32_t>(subject->length(shape))) {
+  subject->TryFlattenIfNotFlat();
+  if (i >= static_cast<uint32_t>(subject->length())) {
     return Heap::nan_value();
   }
-  return Smi::FromInt(subject->Get(shape, i));
+  return Smi::FromInt(subject->Get(i));
 }
 
 
@@ -1114,7 +1113,6 @@ static const int kStringBuilderConcatHelperPositionBits = 19;
 
 template <typename schar>
 static inline void StringBuilderConcatHelper(String*,
-                                             StringShape,
                                              schar*,
                                              FixedArray*,
                                              int);
@@ -1170,11 +1168,10 @@ class ReplacementStringBuilder {
 
 
   void AddString(Handle<String> string) {
-    StringShape shape(*string);
-    int length = string->length(shape);
+    int length = string->length();
     ASSERT(length > 0);
     AddElement(*string);
-    if (!shape.IsAsciiRepresentation()) {
+    if (!StringShape(*string).IsAsciiRepresentation()) {
       is_ascii_ = false;
     }
     IncrementCharacterCount(length);
@@ -1193,7 +1190,6 @@ class ReplacementStringBuilder {
       SeqAsciiString* seq = SeqAsciiString::cast(*joined_string);
       char* char_buffer = seq->GetChars();
       StringBuilderConcatHelper(*subject_,
-                                StringShape(*subject_),
                                 char_buffer,
                                 *parts_,
                                 part_count_);
@@ -1204,7 +1200,6 @@ class ReplacementStringBuilder {
       SeqTwoByteString* seq = SeqTwoByteString::cast(*joined_string);
       uc16* char_buffer = seq->GetChars();
       StringBuilderConcatHelper(*subject_,
-                                StringShape(*subject_),
                                 char_buffer,
                                 *parts_,
                                 part_count_);
@@ -1432,16 +1427,15 @@ class CompiledReplacement {
 void CompiledReplacement::Compile(Handle<String> replacement,
                                   int capture_count,
                                   int subject_length) {
-  StringShape shape(*replacement);
-  ASSERT(replacement->IsFlat(shape));
-  if (shape.IsAsciiRepresentation()) {
+  ASSERT(replacement->IsFlat());
+  if (StringShape(*replacement).IsAsciiRepresentation()) {
     AssertNoAllocation no_alloc;
     ParseReplacementPattern(&parts_,
                             replacement->ToAsciiVector(),
                             capture_count,
                             subject_length);
   } else {
-    ASSERT(shape.IsTwoByteRepresentation());
+    ASSERT(StringShape(*replacement).IsTwoByteRepresentation());
     AssertNoAllocation no_alloc;
 
     ParseReplacementPattern(&parts_,
@@ -1514,8 +1508,8 @@ static Object* StringReplaceRegExpWithString(String* subject,
                                              JSRegExp* regexp,
                                              String* replacement,
                                              JSArray* last_match_info) {
-  ASSERT(subject->IsFlat(StringShape(subject)));
-  ASSERT(replacement->IsFlat(StringShape(replacement)));
+  ASSERT(subject->IsFlat());
+  ASSERT(replacement->IsFlat());
 
   HandleScope handles;
 
@@ -1619,9 +1613,8 @@ static Object* Runtime_StringReplaceRegExpWithString(Arguments args) {
   ASSERT(args.length() == 4);
 
   CONVERT_CHECKED(String, subject, args[0]);
-  StringShape subject_shape(subject);
-  if (!subject->IsFlat(subject_shape)) {
-    Object* flat_subject = subject->TryFlatten(subject_shape);
+  if (!subject->IsFlat()) {
+    Object* flat_subject = subject->TryFlatten();
     if (flat_subject->IsFailure()) {
       return flat_subject;
     }
@@ -1629,9 +1622,8 @@ static Object* Runtime_StringReplaceRegExpWithString(Arguments args) {
   }
 
   CONVERT_CHECKED(String, replacement, args[2]);
-  StringShape replacement_shape(replacement);
-  if (!replacement->IsFlat(replacement_shape)) {
-    Object* flat_replacement = replacement->TryFlatten(replacement_shape);
+  if (!replacement->IsFlat()) {
+    Object* flat_replacement = replacement->TryFlatten();
     if (flat_replacement->IsFailure()) {
       return flat_replacement;
     }
@@ -2002,27 +1994,24 @@ int Runtime::StringMatch(Handle<String> sub,
                          Handle<String> pat,
                          int start_index) {
   ASSERT(0 <= start_index);
-  StringShape sub_shape(*sub);
-  ASSERT(start_index <= sub->length(sub_shape));
+  ASSERT(start_index <= sub->length());
 
   int pattern_length = pat->length();
   if (pattern_length == 0) return start_index;
 
-  int subject_length = sub->length(sub_shape);
+  int subject_length = sub->length();
   if (start_index + pattern_length > subject_length) return -1;
 
-  if (!sub->IsFlat(sub_shape)) {
+  if (!sub->IsFlat()) {
     FlattenString(sub);
-    sub_shape = StringShape(*sub);
   }
-  StringShape pat_shape(*pat);
   // Searching for one specific character is common.  For one
   // character patterns linear search is necessary, so any smart
   // algorithm is unnecessary overhead.
   if (pattern_length == 1) {
     AssertNoAllocation no_heap_allocation;  // ensure vectors stay valid
-    if (sub_shape.IsAsciiRepresentation()) {
-      uc16 pchar = pat->Get(pat_shape, 0);
+    if (StringShape(*sub).IsAsciiRepresentation()) {
+      uc16 pchar = pat->Get(0);
       if (pchar > String::kMaxAsciiCharCode) {
         return -1;
       }
@@ -2037,28 +2026,24 @@ int Runtime::StringMatch(Handle<String> sub,
       return reinterpret_cast<const char*>(pos) - ascii_vector.start()
           + start_index;
     }
-    return SingleCharIndexOf(sub->ToUC16Vector(),
-                             pat->Get(pat_shape, 0),
-                             start_index);
+    return SingleCharIndexOf(sub->ToUC16Vector(), pat->Get(0), start_index);
   }
 
-  if (!pat->IsFlat(pat_shape)) {
+  if (!pat->IsFlat()) {
     FlattenString(pat);
-    pat_shape = StringShape(*pat);
-    sub_shape = StringShape(*sub);
   }
 
   AssertNoAllocation no_heap_allocation;  // ensure vectors stay valid
   // dispatch on type of strings
-  if (pat_shape.IsAsciiRepresentation()) {
+  if (StringShape(*pat).IsAsciiRepresentation()) {
     Vector<const char> pat_vector = pat->ToAsciiVector();
-    if (sub_shape.IsAsciiRepresentation()) {
+    if (StringShape(*sub).IsAsciiRepresentation()) {
       return StringMatchStrategy(sub->ToAsciiVector(), pat_vector, start_index);
     }
     return StringMatchStrategy(sub->ToUC16Vector(), pat_vector, start_index);
   }
   Vector<const uc16> pat_vector = pat->ToUC16Vector();
-  if (sub_shape.IsAsciiRepresentation()) {
+  if (StringShape(*sub).IsAsciiRepresentation()) {
     return StringMatchStrategy(sub->ToAsciiVector(), pat_vector, start_index);
   }
   return StringMatchStrategy(sub->ToUC16Vector(), pat_vector, start_index);
@@ -2090,17 +2075,14 @@ static Object* Runtime_StringLastIndexOf(Arguments args) {
   CONVERT_CHECKED(String, pat, args[1]);
   Object* index = args[2];
 
-  sub->TryFlattenIfNotFlat(StringShape(sub));
-  pat->TryFlattenIfNotFlat(StringShape(pat));
-
-  StringShape sub_shape(sub);
-  StringShape pat_shape(pat);
+  sub->TryFlattenIfNotFlat();
+  pat->TryFlattenIfNotFlat();
 
   uint32_t start_index;
   if (!Array::IndexFromObject(index, &start_index)) return Smi::FromInt(-1);
 
-  uint32_t pattern_length = pat->length(pat_shape);
-  uint32_t sub_length = sub->length(sub_shape);
+  uint32_t pattern_length = pat->length();
+  uint32_t sub_length = sub->length();
 
   if (start_index + pattern_length > sub_length) {
     start_index = sub_length - pattern_length;
@@ -2109,7 +2091,7 @@ static Object* Runtime_StringLastIndexOf(Arguments args) {
   for (int i = start_index; i >= 0; i--) {
     bool found = true;
     for (uint32_t j = 0; j < pattern_length; j++) {
-      if (sub->Get(sub_shape, i + j) != pat->Get(pat_shape, j)) {
+      if (sub->Get(i + j) != pat->Get(j)) {
         found = false;
         break;
       }
@@ -2129,10 +2111,8 @@ static Object* Runtime_StringLocaleCompare(Arguments args) {
   CONVERT_CHECKED(String, str2, args[1]);
 
   if (str1 == str2) return Smi::FromInt(0);  // Equal.
-  StringShape shape1(str1);
-  StringShape shape2(str2);
-  int str1_length = str1->length(shape1);
-  int str2_length = str2->length(shape2);
+  int str1_length = str1->length();
+  int str2_length = str2->length();
 
   // Decide trivial cases without flattening.
   if (str1_length == 0) {
@@ -2147,11 +2127,11 @@ static Object* Runtime_StringLocaleCompare(Arguments args) {
   // No need to flatten if we are going to find the answer on the first
   // character.  At this point we know there is at least one character
   // in each string, due to the trivial case handling above.
-  int d = str1->Get(shape1, 0) - str2->Get(shape2, 0);
+  int d = str1->Get(0) - str2->Get(0);
   if (d != 0) return Smi::FromInt(d);
 
-  str1->TryFlattenIfNotFlat(shape1);  // Shapes are no longer valid now!
-  str2->TryFlattenIfNotFlat(shape2);
+  str1->TryFlattenIfNotFlat();
+  str2->TryFlattenIfNotFlat();
 
   static StringInputBuffer buf1;
   static StringInputBuffer buf2;
@@ -2286,11 +2266,10 @@ static Object* Runtime_NumberToPrecision(Arguments args) {
 // Returns a single character string where first character equals
 // string->Get(index).
 static Handle<Object> GetCharAt(Handle<String> string, uint32_t index) {
-  StringShape shape(*string);
-  if (index < static_cast<uint32_t>(string->length(shape))) {
-    string->TryFlattenIfNotFlat(shape);  // Invalidates shape!
+  if (index < static_cast<uint32_t>(string->length())) {
+    string->TryFlattenIfNotFlat();
     return LookupSingleCharacterStringFromCode(
-        string->Get(StringShape(*string), index));
+        string->Get(index));
   }
   return Execution::CharAt(string, index);
 }
@@ -2481,7 +2460,7 @@ Object* Runtime::SetObjectProperty(Handle<Object> object,
       result = SetElement(js_object, index, value);
     } else {
       Handle<String> key_string = Handle<String>::cast(key);
-      key_string->TryFlattenIfNotFlat(StringShape(*key_string));
+      key_string->TryFlattenIfNotFlat();
       result = SetProperty(js_object, key_string, value, attr);
     }
     if (result.is_null()) return Failure::Exception();
@@ -2775,7 +2754,7 @@ static Object* Runtime_StringToNumber(Arguments args) {
   NoHandleAllocation ha;
   ASSERT(args.length() == 1);
   CONVERT_CHECKED(String, subject, args[0]);
-  subject->TryFlattenIfNotFlat(StringShape(subject));
+  subject->TryFlattenIfNotFlat();
   return Heap::NumberFromDouble(StringToDouble(subject, ALLOW_HEX));
 }
 
@@ -2805,11 +2784,10 @@ static Object* Runtime_StringFromCharCodeArray(Arguments args) {
 
   if (object->IsFailure()) return object;
   String* result = String::cast(object);
-  StringShape result_shape(result);
   for (int i = 0; i < length; i++) {
     Object* element = codes->GetElement(i);
     CONVERT_NUMBER_CHECKED(int, chr, Int32, element);
-    result->Set(result_shape, i, chr & 0xffff);
+    result->Set(i, chr & 0xffff);
   }
   return result;
 }
@@ -2858,7 +2836,7 @@ static Object* Runtime_URIEscape(Arguments args) {
   ASSERT(args.length() == 1);
   CONVERT_CHECKED(String, source, args[0]);
 
-  source->TryFlattenIfNotFlat(StringShape(source));
+  source->TryFlattenIfNotFlat();
 
   int escaped_length = 0;
   int length = source->length();
@@ -2888,7 +2866,6 @@ static Object* Runtime_URIEscape(Arguments args) {
   Object* o = Heap::AllocateRawAsciiString(escaped_length);
   if (o->IsFailure()) return o;
   String* destination = String::cast(o);
-  StringShape dshape(destination);
   int dest_position = 0;
 
   Access<StringInputBuffer> buffer(&runtime_string_input_buffer);
@@ -2896,20 +2873,20 @@ static Object* Runtime_URIEscape(Arguments args) {
   while (buffer->has_more()) {
     uint16_t chr = buffer->GetNext();
     if (chr >= 256) {
-      destination->Set(dshape, dest_position, '%');
-      destination->Set(dshape, dest_position+1, 'u');
-      destination->Set(dshape, dest_position+2, hex_chars[chr >> 12]);
-      destination->Set(dshape, dest_position+3, hex_chars[(chr >> 8) & 0xf]);
-      destination->Set(dshape, dest_position+4, hex_chars[(chr >> 4) & 0xf]);
-      destination->Set(dshape, dest_position+5, hex_chars[chr & 0xf]);
+      destination->Set(dest_position, '%');
+      destination->Set(dest_position+1, 'u');
+      destination->Set(dest_position+2, hex_chars[chr >> 12]);
+      destination->Set(dest_position+3, hex_chars[(chr >> 8) & 0xf]);
+      destination->Set(dest_position+4, hex_chars[(chr >> 4) & 0xf]);
+      destination->Set(dest_position+5, hex_chars[chr & 0xf]);
       dest_position += 6;
     } else if (IsNotEscaped(chr)) {
-      destination->Set(dshape, dest_position, chr);
+      destination->Set(dest_position, chr);
       dest_position++;
     } else {
-      destination->Set(dshape, dest_position, '%');
-      destination->Set(dshape, dest_position+1, hex_chars[chr >> 4]);
-      destination->Set(dshape, dest_position+2, hex_chars[chr & 0xf]);
+      destination->Set(dest_position, '%');
+      destination->Set(dest_position+1, hex_chars[chr >> 4]);
+      destination->Set(dest_position+2, hex_chars[chr & 0xf]);
       dest_position += 3;
     }
   }
@@ -2938,26 +2915,25 @@ static inline int TwoDigitHex(uint16_t character1, uint16_t character2) {
 
 
 static inline int Unescape(String* source,
-                           StringShape shape,
                            int i,
                            int length,
                            int* step) {
-  uint16_t character = source->Get(shape, i);
+  uint16_t character = source->Get(i);
   int32_t hi = 0;
   int32_t lo = 0;
   if (character == '%' &&
       i <= length - 6 &&
-      source->Get(shape, i + 1) == 'u' &&
-      (hi = TwoDigitHex(source->Get(shape, i + 2),
-                        source->Get(shape, i + 3))) != -1 &&
-      (lo = TwoDigitHex(source->Get(shape, i + 4),
-                        source->Get(shape, i + 5))) != -1) {
+      source->Get(i + 1) == 'u' &&
+      (hi = TwoDigitHex(source->Get(i + 2),
+                        source->Get(i + 3))) != -1 &&
+      (lo = TwoDigitHex(source->Get(i + 4),
+                        source->Get(i + 5))) != -1) {
     *step = 6;
     return (hi << 8) + lo;
   } else if (character == '%' &&
       i <= length - 3 &&
-      (lo = TwoDigitHex(source->Get(shape, i + 1),
-                        source->Get(shape, i + 2))) != -1) {
+      (lo = TwoDigitHex(source->Get(i + 1),
+                        source->Get(i + 2))) != -1) {
     *step = 3;
     return lo;
   } else {
@@ -2972,22 +2948,17 @@ static Object* Runtime_URIUnescape(Arguments args) {
   ASSERT(args.length() == 1);
   CONVERT_CHECKED(String, source, args[0]);
 
-  source->TryFlattenIfNotFlat(StringShape(source));
-  StringShape source_shape(source);
+  source->TryFlattenIfNotFlat();
 
   bool ascii = true;
-  int length = source->length(source_shape);
+  int length = source->length();
 
   int unescaped_length = 0;
   for (int i = 0; i < length; unescaped_length++) {
     int step;
-    if (Unescape(source,
-                 source_shape,
-                 i,
-                 length,
-                 &step) >
-        String::kMaxAsciiCharCode)
+    if (Unescape(source, i, length, &step) > String::kMaxAsciiCharCode) {
       ascii = false;
+    }
     i += step;
   }
 
@@ -3000,14 +2971,11 @@ static Object* Runtime_URIUnescape(Arguments args) {
               Heap::AllocateRawTwoByteString(unescaped_length);
   if (o->IsFailure()) return o;
   String* destination = String::cast(o);
-  StringShape destination_shape(destination);
 
   int dest_position = 0;
   for (int i = 0; i < length; dest_position++) {
     int step;
-    destination->Set(destination_shape,
-                     dest_position,
-                     Unescape(source, source_shape, i, length, &step));
+    destination->Set(dest_position, Unescape(source, i, length, &step));
     i += step;
   }
   return destination;
@@ -3021,33 +2989,31 @@ static Object* Runtime_StringParseInt(Arguments args) {
   CONVERT_DOUBLE_CHECKED(n, args[1]);
   int radix = FastD2I(n);
 
-  s->TryFlattenIfNotFlat(StringShape(s));
-
-  StringShape shape(s);
+  s->TryFlattenIfNotFlat();
 
-  int len = s->length(shape);
+  int len = s->length();
   int i;
 
   // Skip leading white space.
-  for (i = 0; i < len && Scanner::kIsWhiteSpace.get(s->Get(shape, i)); i++) ;
+  for (i = 0; i < len && Scanner::kIsWhiteSpace.get(s->Get(i)); i++) ;
   if (i == len) return Heap::nan_value();
 
   // Compute the sign (default to +).
   int sign = 1;
-  if (s->Get(shape, i) == '-') {
+  if (s->Get(i) == '-') {
     sign = -1;
     i++;
-  } else if (s->Get(shape, i) == '+') {
+  } else if (s->Get(i) == '+') {
     i++;
   }
 
   // Compute the radix if 0.
   if (radix == 0) {
     radix = 10;
-    if (i < len && s->Get(shape, i) == '0') {
+    if (i < len && s->Get(i) == '0') {
       radix = 8;
       if (i + 1 < len) {
-        int c = s->Get(shape, i + 1);
+        int c = s->Get(i + 1);
         if (c == 'x' || c == 'X') {
           radix = 16;
           i += 2;
@@ -3056,8 +3022,8 @@ static Object* Runtime_StringParseInt(Arguments args) {
     }
   } else if (radix == 16) {
     // Allow 0x or 0X prefix if radix is 16.
-    if (i + 1 < len && s->Get(shape, i) == '0') {
-      int c = s->Get(shape, i + 1);
+    if (i + 1 < len && s->Get(i) == '0') {
+      int c = s->Get(i + 1);
       if (c == 'x' || c == 'X') i += 2;
     }
   }
@@ -3089,40 +3055,26 @@ static unibrow::Mapping<unibrow::ToLowercase, 128> to_lower_mapping;
 
 
 template <class Converter>
-static Object* ConvertCase(Arguments args,
-                           unibrow::Mapping<Converter, 128>* mapping) {
-  NoHandleAllocation ha;
-
-  CONVERT_CHECKED(String, s, args[0]);
-  s->TryFlattenIfNotFlat(StringShape(s));
-  StringShape shape(s);
-
-  int raw_string_length = s->length(shape);
-  // Assume that the string is not empty; we need this assumption later
-  if (raw_string_length == 0) return s;
-  int length = raw_string_length;
-
-
-  // We try this twice, once with the assumption that the result is
-  // no longer than the input and, if that assumption breaks, again
-  // with the exact length.  This is implemented using a goto back
-  // to this label if we discover that the assumption doesn't hold.
-  // I apologize sincerely for this and will give a vaffel-is to
-  // the first person who can implement it in a nicer way.
- try_convert:
-
+static Object* ConvertCaseHelper(String* s,
+                                 int length,
+                                 int input_string_length,
+                                 unibrow::Mapping<Converter, 128>* mapping) {
+  // We try this twice, once with the assumption that the result is no longer
+  // than the input and, if that assumption breaks, again with the exact
+  // length.  This may not be pretty, but it is nicer than what was here before
+  // and I hereby claim my vaffel-is.
+  //
   // Allocate the resulting string.
   //
   // NOTE: This assumes that the upper/lower case of an ascii
   // character is also ascii.  This is currently the case, but it
   // might break in the future if we implement more context and locale
   // dependent upper/lower conversions.
-  Object* o = shape.IsAsciiRepresentation()
+  Object* o = StringShape(s).IsAsciiRepresentation()
       ? Heap::AllocateRawAsciiString(length)
       : Heap::AllocateRawTwoByteString(length);
   if (o->IsFailure()) return o;
   String* result = String::cast(o);
-  StringShape result_shape(result);
   bool has_changed_character = false;
 
   // Convert all characters to upper case, assuming that they will fit
@@ -3130,24 +3082,23 @@ static Object* ConvertCase(Arguments args,
   Access<StringInputBuffer> buffer(&runtime_string_input_buffer);
   buffer->Reset(s);
   unibrow::uchar chars[Converter::kMaxWidth];
-  int i = 0;
   // We can assume that the string is not empty
   uc32 current = buffer->GetNext();
-  while (i < length) {
+  for (int i = 0; i < length; ) {
     bool has_next = buffer->has_more();
     uc32 next = has_next ? buffer->GetNext() : 0;
     int char_length = mapping->get(current, next, chars);
     if (char_length == 0) {
       // The case conversion of this character is the character itself.
-      result->Set(result_shape, i, current);
+      result->Set(i, current);
       i++;
     } else if (char_length == 1) {
       // Common case: converting the letter resulted in one character.
       ASSERT(static_cast<uc32>(chars[0]) != current);
-      result->Set(result_shape, i, chars[0]);
+      result->Set(i, chars[0]);
       has_changed_character = true;
       i++;
-    } else if (length == raw_string_length) {
+    } else if (length == input_string_length) {
       // We've assumed that the result would be as long as the
       // input but here is a character that converts to several
       // characters.  No matter, we calculate the exact length
@@ -3174,12 +3125,16 @@ static Object* ConvertCase(Arguments args,
         int char_length = mapping->get(current, 0, chars);
         if (char_length == 0) char_length = 1;
         current_length += char_length;
+        if (current_length > Smi::kMaxValue) {
+          Top::context()->mark_out_of_memory();
+          return Failure::OutOfMemoryException();
+        }
       }
-      length = current_length;
-      goto try_convert;
+      // Try again with the real length.
+      return Smi::FromInt(current_length);
     } else {
       for (int j = 0; j < char_length; j++) {
-        result->Set(result_shape, i, chars[j]);
+        result->Set(i, chars[j]);
         i++;
       }
       has_changed_character = true;
@@ -3198,6 +3153,28 @@ static Object* ConvertCase(Arguments args,
 }
 
 
+template <class Converter>
+static Object* ConvertCase(Arguments args,
+                           unibrow::Mapping<Converter, 128>* mapping) {
+  NoHandleAllocation ha;
+
+  CONVERT_CHECKED(String, s, args[0]);
+  s->TryFlattenIfNotFlat();
+
+  int input_string_length = s->length();
+  // Assume that the string is not empty; we need this assumption later
+  if (input_string_length == 0) return s;
+  int length = input_string_length;
+
+  Object* answer = ConvertCaseHelper(s, length, length, mapping);
+  if (answer->IsSmi()) {
+    // Retry with correct length.
+    answer = ConvertCaseHelper(s, Smi::cast(answer)->value(), length, mapping);
+  }
+  return answer;  // This may be a failure.
+}
+
+
 static Object* Runtime_StringToLowerCase(Arguments args) {
   return ConvertCase<unibrow::ToLowercase>(args, &to_lower_mapping);
 }
@@ -3384,7 +3361,6 @@ static Object* Runtime_StringAdd(Arguments args) {
 
 template<typename sinkchar>
 static inline void StringBuilderConcatHelper(String* special,
-                                             StringShape special_shape,
                                              sinkchar* sink,
                                              FixedArray* fixed_array,
                                              int array_length) {
@@ -3396,16 +3372,14 @@ static inline void StringBuilderConcatHelper(String* special,
       int pos = StringBuilderSubstringPosition::decode(encoded_slice);
       int len = StringBuilderSubstringLength::decode(encoded_slice);
       String::WriteToFlat(special,
-                          special_shape,
                           sink + position,
                           pos,
                           pos + len);
       position += len;
     } else {
       String* string = String::cast(element);
-      StringShape shape(string);
-      int element_length = string->length(shape);
-      String::WriteToFlat(string, shape, sink + position, 0, element_length);
+      int element_length = string->length();
+      String::WriteToFlat(string, sink + position, 0, element_length);
       position += element_length;
     }
   }
@@ -3417,8 +3391,7 @@ static Object* Runtime_StringBuilderConcat(Arguments args) {
   ASSERT(args.length() == 2);
   CONVERT_CHECKED(JSArray, array, args[0]);
   CONVERT_CHECKED(String, special, args[1]);
-  StringShape special_shape(special);
-  int special_length = special->length(special_shape);
+  int special_length = special->length();
   Object* smi_array_length = array->length();
   if (!smi_array_length->IsSmi()) {
     Top::context()->mark_out_of_memory();
@@ -3440,7 +3413,7 @@ static Object* Runtime_StringBuilderConcat(Arguments args) {
     if (first->IsString()) return first;
   }
 
-  bool ascii = special_shape.IsAsciiRepresentation();
+  bool ascii = StringShape(special).IsAsciiRepresentation();
   int position = 0;
   for (int i = 0; i < array_length; i++) {
     Object* elt = fixed_array->get(i);
@@ -3454,14 +3427,13 @@ static Object* Runtime_StringBuilderConcat(Arguments args) {
       position += len;
     } else if (elt->IsString()) {
       String* element = String::cast(elt);
-      StringShape element_shape(element);
-      int element_length = element->length(element_shape);
+      int element_length = element->length();
       if (!Smi::IsValid(element_length + position)) {
         Top::context()->mark_out_of_memory();
         return Failure::OutOfMemoryException();
       }
       position += element_length;
-      if (ascii && !element_shape.IsAsciiRepresentation()) {
+      if (ascii && !StringShape(element).IsAsciiRepresentation()) {
         ascii = false;
       }
     } else {
@@ -3477,7 +3449,6 @@ static Object* Runtime_StringBuilderConcat(Arguments args) {
     if (object->IsFailure()) return object;
     SeqAsciiString* answer = SeqAsciiString::cast(object);
     StringBuilderConcatHelper(special,
-                              special_shape,
                               answer->GetChars(),
                               fixed_array,
                               array_length);
@@ -3487,7 +3458,6 @@ static Object* Runtime_StringBuilderConcat(Arguments args) {
     if (object->IsFailure()) return object;
     SeqTwoByteString* answer = SeqTwoByteString::cast(object);
     StringBuilderConcatHelper(special,
-                              special_shape,
                               answer->GetChars(),
                               fixed_array,
                               array_length);
@@ -3682,24 +3652,21 @@ static Object* Runtime_StringCompare(Arguments args) {
   CONVERT_CHECKED(String, x, args[0]);
   CONVERT_CHECKED(String, y, args[1]);
 
-  StringShape x_shape(x);
-  StringShape y_shape(y);
-
   // A few fast case tests before we flatten.
   if (x == y) return Smi::FromInt(EQUAL);
-  if (y->length(y_shape) == 0) {
-    if (x->length(x_shape) == 0) return Smi::FromInt(EQUAL);
+  if (y->length() == 0) {
+    if (x->length() == 0) return Smi::FromInt(EQUAL);
     return Smi::FromInt(GREATER);
-  } else if (x->length(x_shape) == 0) {
+  } else if (x->length() == 0) {
     return Smi::FromInt(LESS);
   }
 
-  int d = x->Get(x_shape, 0) - y->Get(y_shape, 0);
+  int d = x->Get(0) - y->Get(0);
   if (d < 0) return Smi::FromInt(LESS);
   else if (d > 0) return Smi::FromInt(GREATER);
 
-  x->TryFlattenIfNotFlat(x_shape);  // Shapes are no longer valid!
-  y->TryFlattenIfNotFlat(y_shape);
+  x->TryFlattenIfNotFlat();
+  y->TryFlattenIfNotFlat();
 
   static StringInputBuffer bufx;
   static StringInputBuffer bufy;
index a146c4c..e35ac5f 100644 (file)
@@ -254,10 +254,9 @@ TEST(GarbageCollection) {
 
 static void VerifyStringAllocation(const char* string) {
   String* s = String::cast(Heap::AllocateStringFromUtf8(CStrVector(string)));
-  StringShape shape(s);
-  CHECK_EQ(static_cast<int>(strlen(string)), s->length(shape));
-  for (int index = 0; index < s->length(shape); index++) {
-    CHECK_EQ(static_cast<uint16_t>(string[index]), s->Get(shape, index));  }
+  CHECK_EQ(static_cast<int>(strlen(string)), s->length());
+  for (int index = 0; index < s->length(); index++) {
+    CHECK_EQ(static_cast<uint16_t>(string[index]), s->Get(index));  }
 }
 
 
index ed2e9ab..50fe862 100644 (file)
@@ -643,8 +643,7 @@ TEST(MacroAssembler) {
 
   Handle<String> f1 =
       Factory::NewStringFromAscii(CStrVector("foobar"));
-  Handle<String> f1_16 = RegExpImpl::StringToTwoByte(f1);
-  CHECK(IrregexpInterpreter::Match(array, f1_16, captures, 0));
+  CHECK(IrregexpInterpreter::Match(array, f1, captures, 0));
   CHECK_EQ(0, captures[0]);
   CHECK_EQ(3, captures[1]);
   CHECK_EQ(1, captures[2]);
@@ -653,8 +652,7 @@ TEST(MacroAssembler) {
 
   Handle<String> f2 =
       Factory::NewStringFromAscii(CStrVector("barfoo"));
-  Handle<String> f2_16 = RegExpImpl::StringToTwoByte(f2);
-  CHECK(!IrregexpInterpreter::Match(array, f2_16, captures, 0));
+  CHECK(!IrregexpInterpreter::Match(array, f2, captures, 0));
   CHECK_EQ(42, captures[0]);
 }
 
index 0c154bc..f8c1a46 100644 (file)
@@ -62,8 +62,7 @@ static void InitializeBuildingBlocks(
         building_blocks[i] =
             Factory::NewStringFromTwoByte(Vector<const uc16>(buf, len));
         for (int j = 0; j < len; j++) {
-          StringShape shape(*building_blocks[i]);
-          CHECK_EQ(buf[j], building_blocks[i]->Get(shape, j));
+          CHECK_EQ(buf[j], building_blocks[i]->Get(j));
         }
         break;
       }
@@ -75,8 +74,7 @@ static void InitializeBuildingBlocks(
         building_blocks[i] =
             Factory::NewStringFromAscii(Vector<const char>(buf, len));
         for (int j = 0; j < len; j++) {
-          StringShape shape(*building_blocks[i]);
-          CHECK_EQ(buf[j], building_blocks[i]->Get(shape, j));
+          CHECK_EQ(buf[j], building_blocks[i]->Get(j));
         }
         break;
       }
@@ -101,8 +99,7 @@ static void InitializeBuildingBlocks(
         Resource* resource = new Resource(Vector<const uc16>(buf, len));
         building_blocks[i] = Factory::NewExternalStringFromTwoByte(resource);
         for (int j = 0; j < len; j++) {
-          StringShape shape(*building_blocks[i]);
-          CHECK_EQ(buf[j], building_blocks[i]->Get(shape, j));
+          CHECK_EQ(buf[j], building_blocks[i]->Get(j));
         }
         break;
       }
@@ -114,8 +111,7 @@ static void InitializeBuildingBlocks(
         building_blocks[i] =
             Factory::NewStringFromAscii(Vector<const char>(buf, len));
         for (int j = 0; j < len; j++) {
-          StringShape shape(*building_blocks[i]);
-          CHECK_EQ(buf[j], building_blocks[i]->Get(shape, j));
+          CHECK_EQ(buf[j], building_blocks[i]->Get(j));
         }
         DeleteArray<char>(buf);
         break;
@@ -132,9 +128,7 @@ static Handle<String> ConstructLeft(
   for (int i = 0; i < depth; i++) {
     answer = Factory::NewConsString(
         answer,
-        StringShape(*answer),
-        building_blocks[i % NUMBER_OF_BUILDING_BLOCKS],
-        StringShape(*building_blocks[i % NUMBER_OF_BUILDING_BLOCKS]));
+        building_blocks[i % NUMBER_OF_BUILDING_BLOCKS]);
   }
   return answer;
 }
@@ -147,9 +141,7 @@ static Handle<String> ConstructRight(
   for (int i = depth - 1; i >= 0; i--) {
     answer = Factory::NewConsString(
         building_blocks[i % NUMBER_OF_BUILDING_BLOCKS],
-        StringShape(*building_blocks[i % NUMBER_OF_BUILDING_BLOCKS]),
-        answer,
-        StringShape(*answer));
+        answer);
   }
   return answer;
 }
@@ -166,19 +158,13 @@ static Handle<String> ConstructBalancedHelper(
   if (to - from == 2) {
     return Factory::NewConsString(
         building_blocks[from % NUMBER_OF_BUILDING_BLOCKS],
-        StringShape(*building_blocks[from % NUMBER_OF_BUILDING_BLOCKS]),
-        building_blocks[(from+1) % NUMBER_OF_BUILDING_BLOCKS],
-        StringShape(*building_blocks[(from+1) % NUMBER_OF_BUILDING_BLOCKS]));
+        building_blocks[(from+1) % NUMBER_OF_BUILDING_BLOCKS]);
   }
   Handle<String> part1 =
     ConstructBalancedHelper(building_blocks, from, from + ((to - from) / 2));
   Handle<String> part2 =
     ConstructBalancedHelper(building_blocks, from + ((to - from) / 2), to);
-  return Factory::NewConsString(
-      part1,
-      StringShape(*part1),
-      part2,
-      StringShape(*part2));
+  return Factory::NewConsString(part1, part2);
 }
 
 
@@ -216,8 +202,8 @@ static void TraverseFirst(Handle<String> s1, Handle<String> s2, int chars) {
     CHECK_EQ(c, buffer2.GetNext());
     i++;
   }
-  s1->Get(StringShape(*s1), s1->length() - 1);
-  s2->Get(StringShape(*s2), s2->length() - 1);
+  s1->Get(s1->length() - 1);
+  s2->Get(s2->length() - 1);
 }
 
 
@@ -299,19 +285,13 @@ static Handle<String> ConstructSliceTree(
     Handle<String> rhs = building_blocks[(from+1) % NUMBER_OF_BUILDING_BLOCKS];
     if (gen() % 2 == 0)
       rhs = SliceOf(rhs);
-    return Factory::NewConsString(lhs,
-                                  StringShape(*lhs),
-                                  rhs,
-                                  StringShape(*rhs));
+    return Factory::NewConsString(lhs, rhs);
   }
   Handle<String> part1 =
     ConstructBalancedHelper(building_blocks, from, from + ((to - from) / 2));
   Handle<String> part2 =
     ConstructBalancedHelper(building_blocks, from + ((to - from) / 2), to);
-  Handle<String> branch = Factory::NewConsString(part1,
-                                                 StringShape(*part1),
-                                                 part2,
-                                                 StringShape(*part2));
+  Handle<String> branch = Factory::NewConsString(part1, part2);
   if (gen() % 2 == 0)
     return branch;
   return(SliceOf(branch));
@@ -351,15 +331,9 @@ TEST(DeepAscii) {
       Factory::NewStringFromAscii(Vector<const char>(foo, DEEP_ASCII_DEPTH));
   Handle<String> foo_string = Factory::NewStringFromAscii(CStrVector("foo"));
   for (int i = 0; i < DEEP_ASCII_DEPTH; i += 10) {
-    string = Factory::NewConsString(string,
-                                    StringShape(*string),
-                                    foo_string,
-                                    StringShape(*foo_string));
+    string = Factory::NewConsString(string, foo_string);
   }
-  Handle<String> flat_string = Factory::NewConsString(string,
-                                                      StringShape(*string),
-                                                      foo_string,
-                                                      StringShape(*foo_string));
+  Handle<String> flat_string = Factory::NewConsString(string, foo_string);
   FlattenString(flat_string);
 
   for (int i = 0; i < 500; i++) {