Version 2.0.3

Optimized handling and adding of strings, for-in and Array.join.

Heap serialization is now non-destructive.

Improved profiler support with information on time spend in C++ callbacks registered through the API.

Added commands to the debugger protocol for starting/stopping profiling.

Enabled the non-optimizing compiler for top-level code.

Changed the API to only allow strings to be set as data objects on Contexts and scripts to avoid potentially keeping global objects around for too long (issue 528).

OpenBSD support patch by Peter Valchev <pvalchev@gmail.com>.

Fixed bugs.


git-svn-id: http://v8.googlecode.com/svn/trunk@3423 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/src/objects-inl.h b/src/objects-inl.h
index 6919620..8514a41 100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -280,11 +280,6 @@
              Internals::kFullStringRepresentationMask);
 
 
-uint32_t StringShape::size_tag() {
-  return (type_ & kStringSizeMask);
-}
-
-
 bool StringShape::IsSequentialAscii() {
   return full_representation_tag() == (kSeqStringTag | kAsciiStringTag);
 }
@@ -921,25 +916,6 @@
 }
 
 
-bool MapWord::IsSerializationAddress() {
-  return HAS_SMI_TAG(reinterpret_cast<Object*>(value_));
-}
-
-
-MapWord MapWord::FromSerializationAddress(int raw) {
-  // When the map word is being used as a serialization address we Smi-encode
-  // the serialization address (which is always a smallish positive integer).
-  return MapWord(reinterpret_cast<uintptr_t>(Smi::FromInt(raw)));
-}
-
-
-int MapWord::ToSerializationAddress() {
-  // When the map word is being used as a serialization address we treat the
-  // map word as a Smi and get the small integer that it encodes.
-  return reinterpret_cast<Smi*>(value_)->value();
-}
-
-
 bool MapWord::IsMarked() {
   return (value_ & kMarkingMask) == 0;
 }
@@ -1635,6 +1611,19 @@
 INT_ACCESSORS(Array, length, kLengthOffset)
 
 
+INT_ACCESSORS(String, length, kLengthOffset)
+
+
+uint32_t String::hash_field() {
+  return READ_UINT32_FIELD(this, kHashFieldOffset);
+}
+
+
+void String::set_hash_field(uint32_t value) {
+  WRITE_UINT32_FIELD(this, kHashFieldOffset, value);
+}
+
+
 bool String::Equals(String* other) {
   if (other == this) return true;
   if (StringShape(this).IsSymbol() && StringShape(other).IsSymbol()) {
@@ -1644,38 +1633,6 @@
 }
 
 
-int String::length() {
-  uint32_t len = READ_INT_FIELD(this, kLengthOffset);
-
-  ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
-  ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
-  ASSERT(kLongStringTag == 0);
-
-  return len >> (StringShape(this).size_tag() + kLongLengthShift);
-}
-
-
-void String::set_length(int value) {
-  ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
-  ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
-  ASSERT(kLongStringTag == 0);
-
-  WRITE_INT_FIELD(this,
-                  kLengthOffset,
-                  value << (StringShape(this).size_tag() + kLongLengthShift));
-}
-
-
-uint32_t String::length_field() {
-  return READ_UINT32_FIELD(this, kLengthOffset);
-}
-
-
-void String::set_length_field(uint32_t value) {
-  WRITE_UINT32_FIELD(this, kLengthOffset, value);
-}
-
-
 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.
@@ -1779,30 +1736,12 @@
 
 int SeqTwoByteString::SeqTwoByteStringSize(InstanceType instance_type) {
   uint32_t length = READ_INT_FIELD(this, kLengthOffset);
-
-  ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
-  ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
-  ASSERT(kLongStringTag == 0);
-
-  // Use the map (and not 'this') to compute the size tag, since
-  // TwoByteStringSize is called during GC when maps are encoded.
-  length >>= StringShape(instance_type).size_tag() + kLongLengthShift;
-
   return SizeFor(length);
 }
 
 
 int SeqAsciiString::SeqAsciiStringSize(InstanceType instance_type) {
   uint32_t length = READ_INT_FIELD(this, kLengthOffset);
-
-  ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
-  ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
-  ASSERT(kLongStringTag == 0);
-
-  // Use the map (and not 'this') to compute the size tag, since
-  // AsciiStringSize is called during GC when maps are encoded.
-  length >>= StringShape(instance_type).size_tag() + kLongLengthShift;
-
   return SizeFor(length);
 }
 
@@ -1850,34 +1789,6 @@
 }
 
 
-Map* ExternalAsciiString::StringMap(int length) {
-  Map* map;
-  // Number of characters: determines the map.
-  if (length <= String::kMaxShortSize) {
-    map = Heap::short_external_ascii_string_map();
-  } else if (length <= String::kMaxMediumSize) {
-    map = Heap::medium_external_ascii_string_map();
-  } else {
-    map = Heap::long_external_ascii_string_map();
-  }
-  return map;
-}
-
-
-Map* ExternalAsciiString::SymbolMap(int length) {
-  Map* map;
-  // Number of characters: determines the map.
-  if (length <= String::kMaxShortSize) {
-    map = Heap::short_external_ascii_symbol_map();
-  } else if (length <= String::kMaxMediumSize) {
-    map = Heap::medium_external_ascii_symbol_map();
-  } else {
-    map = Heap::long_external_ascii_symbol_map();
-  }
-  return map;
-}
-
-
 ExternalTwoByteString::Resource* ExternalTwoByteString::resource() {
   return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
 }
@@ -1889,34 +1800,6 @@
 }
 
 
-Map* ExternalTwoByteString::StringMap(int length) {
-  Map* map;
-  // Number of characters: determines the map.
-  if (length <= String::kMaxShortSize) {
-    map = Heap::short_external_string_map();
-  } else if (length <= String::kMaxMediumSize) {
-    map = Heap::medium_external_string_map();
-  } else {
-    map = Heap::long_external_string_map();
-  }
-  return map;
-}
-
-
-Map* ExternalTwoByteString::SymbolMap(int length) {
-  Map* map;
-  // Number of characters: determines the map.
-  if (length <= String::kMaxShortSize) {
-    map = Heap::short_external_symbol_map();
-  } else if (length <= String::kMaxMediumSize) {
-    map = Heap::medium_external_symbol_map();
-  } else {
-    map = Heap::long_external_symbol_map();
-  }
-  return map;
-}
-
-
 byte ByteArray::get(int index) {
   ASSERT(index >= 0 && index < this->length());
   return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
@@ -2899,13 +2782,13 @@
 
 
 bool String::HasHashCode() {
-  return (length_field() & kHashComputedMask) != 0;
+  return (hash_field() & kHashComputedMask) != 0;
 }
 
 
 uint32_t String::Hash() {
   // Fast case: has hash code already been computed?
-  uint32_t field = length_field();
+  uint32_t field = hash_field();
   if (field & kHashComputedMask) return field >> kHashShift;
   // Slow case: compute hash code and set it.
   return ComputeAndSetHash();
@@ -2922,7 +2805,7 @@
 
 
 bool StringHasher::has_trivial_hash() {
-  return length_ > String::kMaxMediumSize;
+  return length_ > String::kMaxHashCalcLength;
 }
 
 
@@ -2978,7 +2861,7 @@
 
 
 bool String::AsArrayIndex(uint32_t* index) {
-  uint32_t field = length_field();
+  uint32_t field = hash_field();
   if ((field & kHashComputedMask) && !(field & kIsArrayIndexMask)) return false;
   return SlowAsArrayIndex(index);
 }