Revert "Added ability to lock strings to prevent their representation or encoding...
authorlrn@chromium.org <lrn@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 5 Oct 2011 11:09:34 +0000 (11:09 +0000)
committerlrn@chromium.org <lrn@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 5 Oct 2011 11:09:34 +0000 (11:09 +0000)
This reverts r9424.

Review URL: http://codereview.chromium.org/8143018

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

src/api.cc
src/handles.cc
src/handles.h
src/heap.cc
src/heap.h
src/json-parser.h
src/objects-inl.h
src/objects.cc
src/objects.h
src/runtime.cc
test/cctest/test-api.cc

index ee06456516e3c457d334c845f926a3c3ea0451c3..7266390a42df0da865aa0213713f95d87cb218de 100644 (file)
@@ -4451,9 +4451,6 @@ bool v8::String::MakeExternal(v8::String::ExternalStringResource* resource) {
   if (isolate->string_tracker()->IsFreshUnusedString(obj)) {
     return false;
   }
-  if (isolate->heap()->IsStringLocked(*obj)) {
-    return false;
-  }
   if (isolate->heap()->IsInGCPostProcessing()) {
     return false;
   }
index d3fd12635b152fd8631e166cef19d582677a5028..407a3b59afea54fd842d5840901baa72ffae1301 100644 (file)
@@ -944,20 +944,4 @@ bool CompileOptimized(Handle<JSFunction> function,
   return CompileLazyHelper(&info, flag);
 }
 
-
-void LockString(Handle<String> string) {
-  CALL_HEAP_FUNCTION_VOID(string->GetHeap()->isolate(),
-                          string->GetHeap()->LockString(*string));
-}
-
-
-StringLock::StringLock(Handle<String> string) : string_(string) {
-  LockString(string);
-}
-
-
-StringLock::~StringLock() {
-  string_->GetHeap()->UnlockString(*string_);
-}
-
 } }  // namespace v8::internal
index 31be71459ae8ff868ef95fabba9df256f35c7a90..d5521f89c1e6ef43e49ecc2880e9c26876bc5e31 100644 (file)
@@ -163,11 +163,9 @@ class HandleScope {
 
 // ----------------------------------------------------------------------------
 // Handle operations.
-// They might invoke garbage collection. The result is an handle to an
-// object of expected type, or the handle is a null handle if encountering
-// an internal error. Will not return a null handle due to out-of-memory
-// unless otherwise stated, but will instead try to do GC and die fatally
-// if that doesn't help.
+// They might invoke garbage collection. The result is an handle to
+// an object of expected type, or the handle is an error if running out
+// of space or encountering an internal error.
 
 void NormalizeProperties(Handle<JSObject> object,
                          PropertyNormalizationMode mode,
@@ -185,7 +183,7 @@ MUST_USE_RESULT Handle<NumberDictionary> NumberDictionarySet(
 void FlattenString(Handle<String> str);
 
 // Flattens a string and returns the underlying external or sequential
-// string. Never returns a null handle.
+// string.
 Handle<String> FlattenGetString(Handle<String> str);
 
 Handle<Object> SetProperty(Handle<JSReceiver> object,
@@ -381,22 +379,6 @@ class NoHandleAllocation BASE_EMBEDDED {
 #endif
 };
 
-
-// Prevents a (non-cons, non-slice) string from having its representation
-// changed. This is just a Handle based wrapper around Heap::LockString.
-// Use Heap::UnlockString to unlock (that one can't cause allocation, so
-// it doesn't need a Handle wrapper).
-void LockString(Handle<String> string);
-
-// Scoped lock on a string.
-class StringLock {
- public:
-  explicit StringLock(Handle<String> string);
-  ~StringLock();
- private:
-  Handle<String> string_;
-};
-
 } }  // namespace v8::internal
 
 #endif  // V8_HANDLES_H_
index 8674ba0f7224a83e72d10dbd39807639d2b0e54d..d1f48acbdd66e8e7979ee966632b0b2564f3f376 100644 (file)
@@ -2340,7 +2340,6 @@ bool Heap::CreateInitialObjects() {
   set_intrinsic_function_names(StringDictionary::cast(obj));
 
   if (InitializeNumberStringCache()->IsFailure()) return false;
-  if (InitializeStringLocks()->IsFailure()) return false;
 
   // Allocate cache for single character ASCII strings.
   { MaybeObject* maybe_obj =
@@ -2557,76 +2556,6 @@ MaybeObject* Heap::Uint32ToString(uint32_t value,
 }
 
 
-MaybeObject* Heap::LockString(String* string) {
-  ASSERT(!string->IsConsString());
-  FixedArray* locks = string_locks();
-  ASSERT(locks->length() > 1);
-  int length = locks->length();
-  int element_count = Smi::cast(locks->get(0))->value();
-  int element_index = element_count + 1;
-  if (element_index >= length) {
-    int new_length = length * 2;
-    MaybeObject* allocation = AllocateFixedArray(new_length);
-    FixedArray* new_locks = NULL;  // Initialized to please compiler.
-    if (!allocation->To<FixedArray>(&new_locks)) return allocation;
-    for (int i = 1; i < length; i++) {
-      new_locks->set(i, locks->get(i));
-    }
-    set_string_locks(new_locks);
-    locks = new_locks;
-  }
-  locks->set(element_index, string);
-  locks->set(0, Smi::FromInt(element_index));
-  return string;
-}
-
-
-void Heap::UnlockString(String* string) {
-  FixedArray* locks = string_locks();
-  ASSERT(locks->length() > 1);
-  int element_count = Smi::cast(locks->get(0))->value();
-  ASSERT(element_count > 0);
-  ASSERT(element_count < locks->length());
-  for (int i = 1; i <= element_count; i++) {
-    String* element = String::cast(locks->get(i));
-    if (element == string) {
-      if (i < element_count) {
-        locks->set(i, locks->get(element_count));
-      }
-      locks->set_undefined(element_count);
-      locks->set(0, Smi::FromInt(element_count - 1));
-      return;
-    }
-  }
-  // We should have found the string. It's an error to try to unlock
-  // a string that hasn't been locked.
-  UNREACHABLE();
-}
-
-
-bool Heap::IsStringLocked(String* string) {
-  if (string->IsConsString()) return false;
-  FixedArray* locks = string_locks();
-  ASSERT(locks->length() > 1);
-  int element_count = Smi::cast(locks->get(0))->value();
-  for (int i = 1; i <= element_count; i++) {
-    if (locks->get(i) == string) return true;
-  }
-  return false;
-}
-
-
-MaybeObject* Heap::InitializeStringLocks() {
-  const int kInitialSize = 6;
-  MaybeObject* allocation = AllocateFixedArray(kInitialSize);
-  if (allocation->IsFailure()) return allocation;
-  FixedArray* new_array = FixedArray::cast(allocation->ToObjectUnchecked());
-  new_array->set(0, Smi::FromInt(0));
-  set_string_locks(new_array);
-  return new_array;
-}
-
-
 Map* Heap::MapForExternalArrayType(ExternalArrayType array_type) {
   return Map::cast(roots_[RootIndexForExternalArrayType(array_type)]);
 }
index 499c30ecab8971cf1430b87f91236ad317217b8a..8672db29a4c2baa27cbcd280b79db6c0c5c0f7f2 100644 (file)
@@ -77,7 +77,6 @@ inline Heap* _inline_get_heap_();
   V(Map, hash_table_map, HashTableMap)                                         \
   V(Smi, stack_limit, StackLimit)                                              \
   V(FixedArray, number_string_cache, NumberStringCache)                        \
-  V(FixedArray, string_locks, StringLocks)                        \
   V(Object, instanceof_cache_function, InstanceofCacheFunction)                \
   V(Object, instanceof_cache_map, InstanceofCacheMap)                          \
   V(Object, instanceof_cache_answer, InstanceofCacheAnswer)                    \
@@ -1200,25 +1199,6 @@ class Heap {
   // the string representation of the number.  Otherwise return undefined.
   Object* GetNumberStringCache(Object* number);
 
-  // Locks a string to prevent changes to the string's representation or
-  // encoding, e.g., due to externalization.
-  // It does not prevent moving the string during a GC
-  // (i.e., it's not a way to keep a pointer to an underlying character
-  // sequence valid). Might fail if the underlying data structure can't
-  // grow to accomodate the string, otherwise returns the string itself.
-  //
-  // Stores data in Heap::string_locks(), a FixedArray with the number
-  // of filled in elements in the first position, and that number of
-  // string pointers in the following positions (in no particular order).
-  // The FixedArray is padded with undefined or similar uninteresting values.
-  MaybeObject* LockString(String* string);
-  // Removes the lock on the string.
-  void UnlockString(String* string);
-  // Check if a string is locked.
-  bool IsStringLocked(String* string);
-  // Initializes the data structure underlying LockString.
-  MaybeObject* InitializeStringLocks();
-
   // Update the cache with a new number-string pair.
   void SetNumberStringCache(Object* number, String* str);
 
index 66478938f41d5c619b8d8638a6805e2f170a4893..ca796a69907e090363180d9500cac4797387b916 100644 (file)
 namespace v8 {
 namespace internal {
 
-// A simple JSON parser.
-template <typename StringType>
+// A simple json parser.
+template <bool seq_ascii>
 class JsonParser BASE_EMBEDDED {
  public:
   static Handle<Object> Parse(Handle<String> source) {
-    return JsonParser(Handle<StringType>::cast(source)).ParseJson();
+    return JsonParser().ParseJson(source);
   }
 
   static const int kEndOfString = -1;
 
  private:
-  typedef typename StringType::CharType SourceChar;
-
-  explicit JsonParser(Handle<StringType> source)
-      : isolate_(source->GetHeap()->isolate()),
-        source_(source),
-        characters_(NULL),
-        source_length_(source->length()),
-        position_(-1) {
-    InitializeSource();
-  }
-
-
-  // Parse the source string as containing a single JSON value.
-  Handle<Object> ParseJson();
-
-  // Set up the object so GetChar works, in case it needs more than just
-  // the constructor.
-  void InitializeSource();
-
-  inline uc32 GetChar(int position);
-  inline const SourceChar* GetChars();
+  // Parse a string containing a single JSON value.
+  Handle<Object> ParseJson(Handle<String> source);
 
   inline void Advance() {
     position_++;
     if (position_ >= source_length_) {
       c0_ = kEndOfString;
+    } else if (seq_ascii) {
+      c0_ = seq_source_->SeqAsciiStringGet(position_);
     } else {
-      c0_ = GetChar(position_);
+      c0_ = source_->Get(position_);
     }
   }
 
@@ -85,20 +68,14 @@ class JsonParser BASE_EMBEDDED {
   // section 15.12.1.1. The only allowed whitespace characters between tokens
   // are tab, carriage-return, newline and space.
 
-
-  static inline bool IsJsonWhitespace(uc32 ch) {
-    const char* whitespaces = "\x20\x09\x0a\0\0\x0d\0\0";
-    return (static_cast<uc32>(whitespaces[ch & 0x07]) == ch);
-  }
-
   inline void AdvanceSkipWhitespace() {
     do {
       Advance();
-    } while (IsJsonWhitespace(c0_));
+    } while (c0_ == '\t' || c0_ == '\r' || c0_ == '\n' || c0_ == ' ');
   }
 
   inline void SkipWhitespace() {
-    while (IsJsonWhitespace(c0_)) {
+    while (c0_ == '\t' || c0_ == '\r' || c0_ == '\n' || c0_ == ' ') {
       Advance();
     }
   }
@@ -133,7 +110,7 @@ class JsonParser BASE_EMBEDDED {
   // Creates a new string and copies prefix[start..end] into the beginning
   // of it. Then scans the rest of the string, adding characters after the
   // prefix. Called by ScanJsonString when reaching a '\' or non-ASCII char.
-  template <typename SinkStringType>
+  template <typename StringType, typename SinkChar>
   Handle<String> SlowScanJsonString(Handle<String> prefix, int start, int end);
 
   // A JSON number (production JSONNumber) is a subset of the valid JavaScript
@@ -175,26 +152,37 @@ class JsonParser BASE_EMBEDDED {
 
   static const int kInitialSpecialStringLength = 1024;
 
-  Isolate* isolate_;
-  Handle<StringType> source_;
-  // Used for external strings, to avoid going through the resource on
-  // every access.
-  const SourceChar* characters_;
+
+ private:
+  Handle<String> source_;
   int source_length_;
-  int position_;
+  Handle<SeqAsciiString> seq_source_;
+
+  Isolate* isolate_;
   uc32 c0_;
+  int position_;
 };
 
-template <typename StringType>
-Handle<Object> JsonParser<StringType>::ParseJson() {
-  // Initial position is right before the string.
-  ASSERT(position_ == -1);
+template <bool seq_ascii>
+Handle<Object> JsonParser<seq_ascii>::ParseJson(Handle<String> source) {
+  isolate_ = source->map()->GetHeap()->isolate();
+  FlattenString(source);
+  source_ = source;
+  source_length_ = source_->length();
+
+  // Optimized fast case where we only have ASCII characters.
+  if (seq_ascii) {
+    seq_source_ = Handle<SeqAsciiString>::cast(source_);
+  }
+
+  // Set initial position right before the string.
+  position_ = -1;
   // Advance to the first character (posibly EOS)
   AdvanceSkipWhitespace();
-  // ParseJsonValue also consumes following whitespace.
   Handle<Object> result = ParseJsonValue();
   if (result.is_null() || c0_ != kEndOfString) {
     // Parse failed. Current character is the unexpected token.
+
     const char* message;
     Factory* factory = isolate()->factory();
     Handle<JSArray> array;
@@ -231,7 +219,7 @@ Handle<Object> JsonParser<StringType>::ParseJson() {
         break;
     }
 
-    MessageLocation location(factory->NewScript(source_),
+    MessageLocation location(factory->NewScript(source),
                              position_,
                              position_ + 1);
     Handle<Object> result = factory->NewSyntaxError(message, array);
@@ -243,8 +231,8 @@ Handle<Object> JsonParser<StringType>::ParseJson() {
 
 
 // Parse any JSON value.
-template <typename StringType>
-Handle<Object> JsonParser<StringType>::ParseJsonValue() {
+template <bool seq_ascii>
+Handle<Object> JsonParser<seq_ascii>::ParseJsonValue() {
   switch (c0_) {
     case '"':
       return ParseJsonString();
@@ -295,13 +283,13 @@ Handle<Object> JsonParser<StringType>::ParseJsonValue() {
 
 
 // Parse a JSON object. Position must be right at '{'.
-template <typename StringType>
-Handle<Object> JsonParser<StringType>::ParseJsonObject() {
+template <bool seq_ascii>
+Handle<Object> JsonParser<seq_ascii>::ParseJsonObject() {
   Handle<JSFunction> object_constructor(
       isolate()->global_context()->object_function());
   Handle<JSObject> json_object =
       isolate()->factory()->NewJSObject(object_constructor);
-  ASSERT_EQ('{', c0_);
+  ASSERT_EQ(c0_, '{');
 
   AdvanceSkipWhitespace();
   if (c0_ != '}') {
@@ -331,8 +319,8 @@ Handle<Object> JsonParser<StringType>::ParseJsonObject() {
 }
 
 // Parse a JSON array. Position must be right at '['.
-template <typename StringType>
-Handle<Object> JsonParser<StringType>::ParseJsonArray() {
+template <bool seq_ascii>
+Handle<Object> JsonParser<seq_ascii>::ParseJsonArray() {
   ZoneScope zone_scope(isolate(), DELETE_ON_EXIT);
   ZoneList<Handle<Object> > elements(4);
   ASSERT_EQ(c0_, '[');
@@ -359,8 +347,8 @@ Handle<Object> JsonParser<StringType>::ParseJsonArray() {
 }
 
 
-template <typename StringType>
-Handle<Object> JsonParser<StringType>::ParseJsonNumber() {
+template <bool seq_ascii>
+Handle<Object> JsonParser<seq_ascii>::ParseJsonNumber() {
   bool negative = false;
   int beg_pos = position_;
   if (c0_ == '-') {
@@ -403,12 +391,24 @@ Handle<Object> JsonParser<StringType>::ParseJsonNumber() {
   }
   int length = position_ - beg_pos;
   double number;
-
-  Vector<const SourceChar> chars(GetChars() +  beg_pos, length);
-  number = StringToDouble(isolate()->unicode_cache(),
-                          chars,
-                          NO_FLAGS,  // Hex, octal or trailing junk.
-                          OS::nan_value());
+  if (seq_ascii) {
+    Vector<const char> chars(seq_source_->GetChars() +  beg_pos, length);
+    number = StringToDouble(isolate()->unicode_cache(),
+                             chars,
+                             NO_FLAGS,  // Hex, octal or trailing junk.
+                             OS::nan_value());
+  } else {
+    Vector<char> buffer = Vector<char>::New(length);
+    String::WriteToFlat(*source_, buffer.start(), beg_pos, position_);
+    Vector<const char> result =
+        Vector<const char>(reinterpret_cast<const char*>(buffer.start()),
+        length);
+    number = StringToDouble(isolate()->unicode_cache(),
+                             result,
+                             NO_FLAGS,  // Hex, octal or trailing junk.
+                             0.0);
+    buffer.Dispose();
+  }
   SkipWhitespace();
   return isolate()->factory()->NewNumber(number);
 }
@@ -444,17 +444,15 @@ inline Handle<SeqAsciiString> NewRawString(Factory* factory, int length) {
 // Scans the rest of a JSON string starting from position_ and writes
 // prefix[start..end] along with the scanned characters into a
 // sequential string of type StringType.
-template <typename StringType>
-template <typename SinkStringType>
-Handle<String> JsonParser<StringType>::SlowScanJsonString(
+template <bool seq_ascii>
+template <typename StringType, typename SinkChar>
+Handle<String> JsonParser<seq_ascii>::SlowScanJsonString(
     Handle<String> prefix, int start, int end) {
-  typedef typename SinkStringType::CharType SinkChar;
   int count = end - start;
   int max_length = count + source_length_ - position_;
   int length = Min(max_length, Max(kInitialSpecialStringLength, 2 * count));
-  Handle<SinkStringType> seq_str =
-      NewRawString<SinkStringType>(isolate()->factory(),
-                                   length);
+  Handle<StringType> seq_str = NewRawString<StringType>(isolate()->factory(),
+                                                        length);
   // Copy prefix into seq_str.
   SinkChar* dest = seq_str->GetChars();
   String::WriteToFlat(*prefix, dest, start, end);
@@ -464,7 +462,7 @@ Handle<String> JsonParser<StringType>::SlowScanJsonString(
     if (c0_ < 0x20) return Handle<String>::null();
     if (count >= length) {
       // We need to create a longer sequential string for the result.
-      return SlowScanJsonString<SinkStringType>(seq_str, 0, count);
+      return SlowScanJsonString<StringType, SinkChar>(seq_str, 0, count);
     }
     if (c0_ != '\\') {
       // If the sink can contain UC16 characters, or source_ contains only
@@ -472,16 +470,16 @@ Handle<String> JsonParser<StringType>::SlowScanJsonString(
       // character. Otherwise check whether the UC16 source character can fit
       // in the ASCII sink.
       if (sizeof(SinkChar) == kUC16Size ||
-          sizeof(SourceChar) == kCharSize ||
+          seq_ascii ||
           c0_ <= kMaxAsciiCharCode) {
         SeqStringSet(seq_str, count++, c0_);
         Advance();
       } else {
-        // SinkStringType is SeqAsciiString and we just read a non-ASCII char.
-        return SlowScanJsonString<SeqTwoByteString>(seq_str, 0, count);
+        // StringType is SeqAsciiString and we just read a non-ASCII char.
+        return SlowScanJsonString<SeqTwoByteString, uc16>(seq_str, 0, count);
       }
     } else {
-      Advance();  // Advance past the '\'.
+      Advance();  // Advance past the \.
       switch (c0_) {
         case '"':
         case '\\':
@@ -520,9 +518,9 @@ Handle<String> JsonParser<StringType>::SlowScanJsonString(
             // StringType is SeqAsciiString and we just read a non-ASCII char.
             position_ -= 6;  // Rewind position_ to \ in \uxxxx.
             Advance();
-            return SlowScanJsonString<SeqTwoByteString>(seq_str,
-                                                        0,
-                                                        count);
+            return SlowScanJsonString<SeqTwoByteString, uc16>(seq_str,
+                                                              0,
+                                                              count);
           }
         }
         default:
@@ -534,11 +532,11 @@ Handle<String> JsonParser<StringType>::SlowScanJsonString(
   // Shrink seq_string length to count.
   if (isolate()->heap()->InNewSpace(*seq_str)) {
     isolate()->heap()->new_space()->
-        template ShrinkStringAtAllocationBoundary<SinkStringType>(
+        template ShrinkStringAtAllocationBoundary<StringType>(
             *seq_str, count);
   } else {
-    int string_size = SinkStringType::SizeFor(count);
-    int allocated_string_size = SinkStringType::SizeFor(length);
+    int string_size = StringType::SizeFor(count);
+    int allocated_string_size = StringType::SizeFor(length);
     int delta = allocated_string_size - string_size;
     Address start_filler_object = seq_str->address() + string_size;
     seq_str->set_length(count);
@@ -551,9 +549,9 @@ Handle<String> JsonParser<StringType>::SlowScanJsonString(
 }
 
 
-template <typename StringType>
+template <bool seq_ascii>
 template <bool is_symbol>
-Handle<String> JsonParser<StringType>::ScanJsonString() {
+Handle<String> JsonParser<seq_ascii>::ScanJsonString() {
   ASSERT_EQ('"', c0_);
   Advance();
   if (c0_ == '"') {
@@ -566,24 +564,25 @@ Handle<String> JsonParser<StringType>::ScanJsonString() {
     // Check for control character (0x00-0x1f) or unterminated string (<0).
     if (c0_ < 0x20) return Handle<String>::null();
     if (c0_ != '\\') {
-      if (c0_ <= kMaxAsciiCharCode) {
+      if (seq_ascii || c0_ <= kMaxAsciiCharCode) {
         Advance();
       } else {
-        return SlowScanJsonString<SeqTwoByteString>(source_,
-                                                    beg_pos,
-                                                    position_);
+        return SlowScanJsonString<SeqTwoByteString, uc16>(source_,
+                                                          beg_pos,
+                                                          position_);
       }
     } else {
-      return SlowScanJsonString<SeqAsciiString>(source_,
-                                                beg_pos,
-                                                position_);
+      return SlowScanJsonString<SeqAsciiString, char>(source_,
+                                                      beg_pos,
+                                                      position_);
     }
   } while (c0_ != '"');
   int length = position_ - beg_pos;
   Handle<String> result;
-  if (is_symbol && source_->IsSeqAsciiString()) {
-    result = isolate()->factory()->LookupAsciiSymbol(
-         Handle<SeqAsciiString>::cast(source_), beg_pos, length);
+  if (seq_ascii && is_symbol) {
+    result = isolate()->factory()->LookupAsciiSymbol(seq_source_,
+                                                     beg_pos,
+                                                     length);
   } else {
     result = isolate()->factory()->NewRawAsciiString(length);
     char* dest = SeqAsciiString::cast(*result)->GetChars();
@@ -595,74 +594,6 @@ Handle<String> JsonParser<StringType>::ScanJsonString() {
   return result;
 }
 
-
-template <typename StringType>
-void JsonParser<StringType>::InitializeSource() { }
-
-
-template <>
-void JsonParser<ExternalAsciiString>::InitializeSource() {
-  characters_ = source_->resource()->data();
-}
-
-
-template <>
-void JsonParser<ExternalTwoByteString>::InitializeSource() {
-  characters_ = source_->resource()->data();
-}
-
-
-template <>
-uc32 JsonParser<SeqAsciiString>::GetChar(int pos) {
-  return static_cast<uc32>(source_->SeqAsciiStringGet(pos));
-}
-
-
-template <>
-uc32 JsonParser<SeqTwoByteString>::GetChar(int pos) {
-  return static_cast<uc32>(source_->SeqTwoByteStringGet(pos));
-}
-
-
-template <>
-uc32 JsonParser<ExternalAsciiString>::GetChar(int pos) {
-  ASSERT(pos >= 0);
-  ASSERT(pos < source_length_);
-  return static_cast<uc32>(characters_[pos]);
-}
-
-
-template <>
-uc32 JsonParser<ExternalTwoByteString>::GetChar(int pos) {
-  ASSERT(pos >= 0);
-  ASSERT(pos < source_length_);
-  return static_cast<uc32>(characters_[pos]);
-}
-
-
-template <>
-const char* JsonParser<SeqAsciiString>::GetChars() {
-  return source_->GetChars();
-}
-
-
-template <>
-const uc16* JsonParser<SeqTwoByteString>::GetChars() {
-  return source_->GetChars();
-}
-
-
-template <>
-const char* JsonParser<ExternalAsciiString>::GetChars() {
-  return characters_;
-}
-
-
-template <>
-const uc16* JsonParser<ExternalTwoByteString>::GetChars() {
-  return characters_;
-}
-
 } }  // namespace v8::internal
 
 #endif  // V8_JSON_PARSER_H_
index 6509f136caede0ac754f6053ae0a91ce67578933..c579d373f7207416134bfd8d47dd7f8a539c9e90 100644 (file)
@@ -37,7 +37,6 @@
 
 #include "elements.h"
 #include "objects.h"
-#include "char-predicates-inl.h"
 #include "contexts.h"
 #include "conversions-inl.h"
 #include "heap.h"
@@ -4218,6 +4217,7 @@ StringHasher::StringHasher(int length)
     raw_running_hash_(0),
     array_index_(0),
     is_array_index_(0 < length_ && length_ <= String::kMaxArrayIndexSize),
+    is_first_char_(true),
     is_valid_(true) { }
 
 
@@ -4229,18 +4229,26 @@ bool StringHasher::has_trivial_hash() {
 void StringHasher::AddCharacter(uc32 c) {
   // Use the Jenkins one-at-a-time hash function to update the hash
   // for the given character.
-  raw_running_hash_ = (raw_running_hash_ + c) * 1025;
+  raw_running_hash_ += c;
+  raw_running_hash_ += (raw_running_hash_ << 10);
   raw_running_hash_ ^= (raw_running_hash_ >> 6);
+  // Incremental array index computation.
   if (is_array_index_) {
-    // Incremental array index computation.
-    unsigned digit = static_cast<unsigned>(c) - '0';
-    if (digit > 9 || array_index_ > 429496729U - ((digit + 2) >> 3)) {
+    if (c < '0' || c > '9') {
       is_array_index_ = false;
     } else {
-      array_index_ = array_index_ * 10 + digit;
-      // Check for overflows or prefixed zeros (lengths > 0).
-      if (array_index_ == 0 && length_ > 1) {
+      int d = c - '0';
+      if (is_first_char_) {
+        is_first_char_ = false;
+        if (c == '0' && length_ > 1) {
+          is_array_index_ = false;
+          return;
+        }
+      }
+      if (array_index_ > 429496729U - ((d + 2) >> 3)) {
         is_array_index_ = false;
+      } else {
+        array_index_ = array_index_ * 10 + d;
       }
     }
   }
@@ -4249,7 +4257,8 @@ void StringHasher::AddCharacter(uc32 c) {
 
 void StringHasher::AddCharacterNoIndex(uc32 c) {
   ASSERT(!is_array_index());
-  raw_running_hash_ = (raw_running_hash_ + c) * 1025;
+  raw_running_hash_ += c;
+  raw_running_hash_ += (raw_running_hash_ << 10);
   raw_running_hash_ ^= (raw_running_hash_ >> 6);
 }
 
index 3e280fd79f8966db9fd6ee0a9c5e79ed6e11a48b..b77dd1b585c0b3807a1e515390ee34da4053d9de 100644 (file)
@@ -2822,8 +2822,7 @@ MaybeObject* JSObject::SetLocalPropertyIgnoreAttributes(
         attributes);
   }
 
-  // Unlike SetLocalProperty, we ignore the prototype chain and
-  // any accessors in it.
+  // Check for accessor in prototype chain removed here in clone.
   if (!result.IsFound()) {
     // Neither properties nor transitions found.
     return AddProperty(name, value, attributes, kNonStrictMode);
@@ -10224,8 +10223,6 @@ class SubStringAsciiSymbolKey : public HashTableKey {
     ASSERT(length_ >= 0);
     ASSERT(from_ + length_ <= string_->length());
     StringHasher hasher(length_);
-    AssertNoAllocation no_alloc;
-    const char* chars = string_->GetChars() + from_;
 
     // Very long strings have a trivial hash that doesn't inspect the
     // string contents.
@@ -10236,14 +10233,16 @@ class SubStringAsciiSymbolKey : public HashTableKey {
       // Do the iterative array index computation as long as there is a
       // chance this is an array index.
       while (i < length_ && hasher.is_array_index()) {
-        hasher.AddCharacter(static_cast<uc32>(chars[i]));
+        hasher.AddCharacter(static_cast<uc32>(
+            string_->SeqAsciiStringGet(i + from_)));
         i++;
       }
 
       // Process the remaining characters without updating the array
       // index.
       while (i < length_) {
-        hasher.AddCharacterNoIndex(static_cast<uc32>(chars[i]));
+        hasher.AddCharacterNoIndex(static_cast<uc32>(
+            string_->SeqAsciiStringGet(i + from_)));
         i++;
       }
       hash_field_ = hasher.GetHashField();
index 74fb01257954d77788f4e3cfa2bf16d478b0f1fa..7e531b28ae38ebbb5092934e196f483384cfddaf 100644 (file)
@@ -5766,6 +5766,7 @@ class StringHasher {
   uint32_t raw_running_hash_;
   uint32_t array_index_;
   bool is_array_index_;
+  bool is_first_char_;
   bool is_valid_;
   friend class TwoCharHashTableKey;
 };
@@ -6217,25 +6218,15 @@ class SeqString: public String {
   // Layout description.
   static const int kHeaderSize = String::kSize;
 
-  // Shortcuts for templates that know their string-type exactly.
-  bool IsExternalAsciiString() {
-    return false;
-  }
-  bool IsExternalTwoByteString() {
-    return false;
-  }
-
-
  private:
   DISALLOW_IMPLICIT_CONSTRUCTORS(SeqString);
 };
 
 
-// The SeqAsciiString class captures sequential ASCII string objects.
-// Each character in the AsciiString is an ASCII character.
+// The AsciiString class captures sequential ascii string objects.
+// Each character in the AsciiString is an ascii character.
 class SeqAsciiString: public SeqString {
  public:
-  typedef char CharType;
   static const bool kHasAsciiEncoding = true;
 
   // Dispatched behavior.
@@ -6250,15 +6241,6 @@ class SeqAsciiString: public SeqString {
   // Casting
   static inline SeqAsciiString* cast(Object* obj);
 
-  bool IsSeqAsciiString() {
-    ASSERT(this->Object::IsSeqAsciiString());
-    return true;
-  }
-  bool IsSeqTwoByteString() {
-    ASSERT(this->Object::IsSeqAsciiString());
-    return false;
-  }
-
   // Garbage collection support.  This method is called by the
   // garbage collector to compute the actual size of an AsciiString
   // instance.
@@ -6288,12 +6270,10 @@ class SeqAsciiString: public SeqString {
 };
 
 
-// The SeqTwoByteString class captures sequential unicode string objects.
+// The TwoByteString class captures sequential unicode string objects.
 // Each character in the TwoByteString is a two-byte uint16_t.
 class SeqTwoByteString: public SeqString {
  public:
-  typedef uc16 CharType;
-
   static const bool kHasAsciiEncoding = false;
 
   // Dispatched behavior.
@@ -6310,14 +6290,6 @@ class SeqTwoByteString: public SeqString {
 
   // Casting
   static inline SeqTwoByteString* cast(Object* obj);
-  bool IsSeqTwoByteString() {
-    ASSERT(this->Object::IsSeqTwoByteString());
-    return true;
-  }
-  bool IsSeqAsciiString() {
-    ASSERT(this->Object::IsSeqTwoByteString());
-    return false;
-  }
 
   // Garbage collection support.  This method is called by the
   // garbage collector to compute the actual size of a TwoByteString
@@ -6478,14 +6450,6 @@ class ExternalString: public String {
 
   STATIC_CHECK(kResourceOffset == Internals::kStringResourceOffset);
 
-  // Shortcuts for templates that know their string type exactly.
-  bool IsSeqAsciiString() {
-    return false;
-  }
-  bool IsSeqTwoByteString() {
-    return false;
-  }
-
  private:
   DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalString);
 };
@@ -6495,8 +6459,6 @@ class ExternalString: public String {
 // ASCII string.
 class ExternalAsciiString: public ExternalString {
  public:
-  typedef char CharType;
-
   static const bool kHasAsciiEncoding = true;
 
   typedef v8::String::ExternalAsciiStringResource Resource;
@@ -6510,14 +6472,6 @@ class ExternalAsciiString: public ExternalString {
 
   // Casting.
   static inline ExternalAsciiString* cast(Object* obj);
-  bool IsExternalAsciiString() {
-    ASSERT(this->Object::IsExternalAsciiString());
-    return true;
-  }
-  bool IsExternalTwoByteString() {
-    ASSERT(this->Object::IsExternalAsciiString());
-    return false;
-  }
 
   // Garbage collection support.
   inline void ExternalAsciiStringIterateBody(ObjectVisitor* v);
@@ -6538,11 +6492,10 @@ class ExternalAsciiString: public ExternalString {
 };
 
 
-// The ExternalTwoByteString class is an external string backed by a 16-bit
-// character sequence.
+// The ExternalTwoByteString class is an external string backed by a UTF-16
+// encoded string.
 class ExternalTwoByteString: public ExternalString {
  public:
-  typedef uc16 CharType;
   static const bool kHasAsciiEncoding = false;
 
   typedef v8::String::ExternalStringResource Resource;
@@ -6559,14 +6512,6 @@ class ExternalTwoByteString: public ExternalString {
 
   // Casting.
   static inline ExternalTwoByteString* cast(Object* obj);
-  bool IsExternalTwoByteString() {
-    ASSERT(this->Object::IsExternalTwoByteString());
-    return true;
-  }
-  bool IsExternalAsciiString() {
-    ASSERT(this->Object::IsExternalTwoByteString());
-    return false;
-  }
 
   // Garbage collection support.
   inline void ExternalTwoByteStringIterateBody(ObjectVisitor* v);
index 0e1ae4484948d806817af5b66ba71ae65f0f5802..1f52a225de9ceee3a4cefc1d0e1d1e8b785da2e4 100644 (file)
@@ -9139,22 +9139,13 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_ParseJson) {
   ASSERT_EQ(1, args.length());
   CONVERT_ARG_CHECKED(String, source, 0);
 
-  source = FlattenGetString(source);
-  ASSERT(!source->IsConsString());
-  ASSERT(!source->IsSlicedString());
+  source = Handle<String>(source->TryFlattenGetString());
+  // Optimized fast case where we only have ascii characters.
   Handle<Object> result;
-  {
-    StringLock lock_representation(source);
-    if (source->IsSeqAsciiString()) {
-      result = JsonParser<SeqAsciiString>::Parse(source);
-    } else if (source->IsExternalTwoByteString()) {
-      result = JsonParser<ExternalTwoByteString>::Parse(source);
-    } else if (source->IsSeqTwoByteString()) {
-      result = JsonParser<SeqTwoByteString>::Parse(source);
-    } else {
-      ASSERT(source->IsExternalAsciiString());
-      result = JsonParser<ExternalAsciiString>::Parse(source);
-    }
+  if (source->IsSeqAsciiString()) {
+    result = JsonParser<true>::Parse(source);
+  } else {
+    result = JsonParser<false>::Parse(source);
   }
   if (result.is_null()) {
     // Syntax error or stack overflow in scanner.
index 88b925f261f4e3619d62d13154ab01795662e41f..167c4cd15518d9ae1441aa9f4554e41fb370c717 100644 (file)
@@ -33,7 +33,6 @@
 #include "isolate.h"
 #include "compilation-cache.h"
 #include "execution.h"
-#include "handles.h"
 #include "snapshot.h"
 #include "platform.h"
 #include "utils.h"
@@ -15441,223 +15440,3 @@ THREADED_TEST(ForeignFunctionReceiver) {
 
   foreign_context.Dispose();
 }
-
-
-
-class SimpleTestResource: public String::ExternalStringResource {
- public:
-  explicit SimpleTestResource(const uint16_t* data) : data_(data), length_(0) {
-    while (data[length_] != 0) length_++;
-  }
-  virtual ~SimpleTestResource() { }
-  virtual const uint16_t* data() const { return data_; }
-  virtual size_t length() const { return length_; }
- private:
-  const uint16_t* data_;
-  int length_;
-};
-
-
-THREADED_TEST(StringLock) {
-  v8::HandleScope scope;
-  LocalContext env;
-
-  i::Isolate* isolate = i::Isolate::Current();
-  i::Heap* heap = isolate->heap();
-
-  // ASCII text of test strings.
-  const char* text = "Lorem ipsum dolor sic amet.";
-  const size_t kTextLength = 27;
-  CHECK(strlen(text) == kTextLength);
-  // UC16 version of string.
-  uint16_t uc16_text[kTextLength + 1];
-  for (unsigned i = 0; i <= kTextLength; i++) {
-    uc16_text[i] = static_cast<uint16_t>(text[i]);
-  }
-
-  // Create some different strings and move them to old-space,
-  // so that externalization can succeede.
-  Local<String> s1 = v8_str(text);
-  Local<String> s2 = v8_str(text + 1);
-  Local<String> s3 = v8_str(text + 2);
-  heap->CollectGarbage(i::NEW_SPACE);
-  heap->CollectGarbage(i::NEW_SPACE);
-
-  SimpleTestResource* r1 = new SimpleTestResource(uc16_text);
-  SimpleTestResource* r2 = new SimpleTestResource(uc16_text + 1);
-  SimpleTestResource* r3 = new SimpleTestResource(uc16_text + 2);
-
-  // Check that externalization works.
-  CHECK(!s1->IsExternal());
-  CHECK(s1->MakeExternal(r1));
-  CHECK(s1->IsExternal());
-
-  // Externalize while the string is locked.
-
-  // Use the direct interface to string locking.
-  i::Handle<i::String> s2i(v8::Utils::OpenHandle(*s2));
-  CHECK(!heap->IsStringLocked(*s2i));
-  LockString(s2i);  // Use handle version, not Heap::LockString, to allow GC.
-  CHECK(isolate->heap()->IsStringLocked(*s2i));
-
-  CHECK(!s2->IsExternal());
-  CHECK(!s2->MakeExternal(r2));
-  CHECK(!s2->IsExternal());
-
-  CHECK(heap->IsStringLocked(*s2i));
-  heap->UnlockString(*s2i);
-  CHECK(!heap->IsStringLocked(*s2i));
-
-  CHECK(!s2->IsExternal());
-  CHECK(s2->MakeExternal(r2));
-  CHECK(s2->IsExternal());
-
-  // Use the Handle-based scoped StringLock.
-  i::Handle<i::String> s3i(v8::Utils::OpenHandle(*s3));
-  {
-    CHECK(!heap->IsStringLocked(*s3i));
-    i::StringLock lock(s3i);
-    CHECK(heap->IsStringLocked(*s3i));
-
-    CHECK(!s3->IsExternal());
-    CHECK(!s3->MakeExternal(r3));
-    CHECK(!s3->IsExternal());
-
-    CHECK(heap->IsStringLocked(*s3i));
-  }
-  CHECK(!heap->IsStringLocked(*s3i));
-
-  CHECK(!s3->IsExternal());
-  CHECK(s3->MakeExternal(r3));
-  CHECK(s3->IsExternal());
-}
-
-
-THREADED_TEST(MultiStringLock) {
-  v8::HandleScope scope;
-  LocalContext env;
-  i::Isolate* isolate = i::Isolate::Current();
-  i::Heap* heap = isolate->heap();
-  const char* text = "Lorem ipsum dolor sic amet.";
-
-  const int N = 16;  // Must be power of 2.
-  CHECK_GT(strlen(text), static_cast<size_t>(N));
-
-  // Create a bunch of different strings.
-  i::Handle<i::String> strings[N];
-
-  for (int i = 0; i < N; i++) {
-    Local<String> s = v8_str(text + i);
-    strings[i] = v8::Utils::OpenHandle(*s);
-  }
-
-  heap->CollectGarbage(i::NEW_SPACE);
-  heap->CollectGarbage(i::NEW_SPACE);
-
-  // Check that start out are unlocked.
-  for (int i = 0; i < N; i++) {
-    CHECK(!heap->IsStringLocked(*strings[i]));
-  }
-
-  // Lock them, one at a time.
-  for (int i = 0; i < N; i++) {
-    LockString(strings[i]);
-    for (int j = 0; j < N; j++) {
-      if (j <= i) {
-        CHECK(heap->IsStringLocked(*strings[j]));
-      } else {
-        CHECK(!heap->IsStringLocked(*strings[j]));
-      }
-    }
-  }
-
-  // Unlock them in a slightly different order (not same as locking,
-  // nor the reverse order).
-  for (int i = 0; i < N; i++) {
-    int mix_i = i ^ 3;
-    heap->UnlockString(*strings[mix_i]);
-    for (int j = 0; j < N; j++) {
-      int unmix_j =  j ^ 3;
-      if (unmix_j <= i) {
-        CHECK(!heap->IsStringLocked(*strings[j]));
-      } else {
-        CHECK(heap->IsStringLocked(*strings[j]));
-      }
-    }
-  }
-}
-
-
-THREADED_TEST(DuplicateStringLock) {
-  v8::HandleScope scope;
-  LocalContext env;
-  i::Isolate* isolate = i::Isolate::Current();
-  i::Heap* heap = isolate->heap();
-  const char* text = "Lorem ipsum dolor sic amet.";
-
-  const int N = 16;  // Must be power of 2.
-  CHECK_GT(strlen(text), static_cast<size_t>(N));
-
-  // Create a bunch of different strings.
-  i::Handle<i::String> strings[N];
-
-  for (int i = 0; i < N; i++) {
-    Local<String> s = v8_str(text + i);
-    strings[i] = v8::Utils::OpenHandle(*s);
-  }
-
-  heap->CollectGarbage(i::NEW_SPACE);
-  heap->CollectGarbage(i::NEW_SPACE);
-
-  // Check that strings start out unlocked.
-  for (int i = 0; i < N; i++) {
-    CHECK(!heap->IsStringLocked(*strings[i]));
-  }
-
-  // Lock them, one at a time.
-  for (int i = 0; i < N; i++) {
-    LockString(strings[i]);
-    for (int j = 0; j < N; j++) {
-      if (j <= i) {
-        CHECK(heap->IsStringLocked(*strings[j]));
-      } else {
-        CHECK(!heap->IsStringLocked(*strings[j]));
-      }
-    }
-  }
-
-  // Lock the first half of them a second time.
-  for (int i = 0; i < N / 2; i++) {
-    LockString(strings[i]);
-    for (int j = 0; j < N; j++) {
-      CHECK(heap->IsStringLocked(*strings[j]));
-    }
-  }
-
-  // Unlock them in a slightly different order (not same as locking,
-  // nor the reverse order).
-  for (int i = 0; i < N; i++) {
-    int mix_i = i ^ 3;
-    heap->UnlockString(*strings[mix_i]);
-    for (int j = 0; j < N; j++) {
-      int unmix_j =  j ^ 3;
-      if (unmix_j <= i && j >= N / 2) {
-        CHECK(!heap->IsStringLocked(*strings[j]));
-      } else {
-        CHECK(heap->IsStringLocked(*strings[j]));
-      }
-    }
-  }
-
-  // Unlock the first half again.
-  for (int i = 0; i < N / 2; i++) {
-    heap->UnlockString(*strings[i]);
-    for (int j = 0; j < N; j++) {
-      if (j <= i || j >= N/ 2) {
-        CHECK(!heap->IsStringLocked(*strings[j]));
-      } else {
-        CHECK(heap->IsStringLocked(*strings[j]));
-      }
-    }
-  }
-}