Push version 1.2.2 to trunk.

Fixed bug in array sorting for sparse arrays (issue 326).

Added support for adding a soname when building a shared library on Linux (issue 151).

Fixed bug caused by morphing internal ASCII strings to external two-byte strings.  Slices over ASCII strings have to forward ASCII checks to the underlying buffer string.

Allowed API call-as-function handlers to be called as constructors.

Fixed a crash bug where an external string was disposed but a slice of the external string survived as a symbol.



git-svn-id: http://v8.googlecode.com/svn/trunk@1853 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/src/runtime.cc b/src/runtime.cc
index a1e23b4..3a738df 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -1282,7 +1282,7 @@
         parts_(Factory::NewFixedArray(estimated_part_count)),
         part_count_(0),
         character_count_(0),
-        is_ascii_(StringShape(*subject).IsAsciiRepresentation()) {
+        is_ascii_(subject->IsAsciiRepresentation()) {
     // Require a non-zero initial size. Ensures that doubling the size to
     // extend the array will work.
     ASSERT(estimated_part_count > 0);
@@ -1326,7 +1326,7 @@
     int length = string->length();
     ASSERT(length > 0);
     AddElement(*string);
-    if (!StringShape(*string).IsAsciiRepresentation()) {
+    if (!string->IsAsciiRepresentation()) {
       is_ascii_ = false;
     }
     IncrementCharacterCount(length);
@@ -1583,14 +1583,14 @@
                                   int capture_count,
                                   int subject_length) {
   ASSERT(replacement->IsFlat());
-  if (StringShape(*replacement).IsAsciiRepresentation()) {
+  if (replacement->IsAsciiRepresentation()) {
     AssertNoAllocation no_alloc;
     ParseReplacementPattern(&parts_,
                             replacement->ToAsciiVector(),
                             capture_count,
                             subject_length);
   } else {
-    ASSERT(StringShape(*replacement).IsTwoByteRepresentation());
+    ASSERT(replacement->IsTwoByteRepresentation());
     AssertNoAllocation no_alloc;
 
     ParseReplacementPattern(&parts_,
@@ -2165,7 +2165,7 @@
   // algorithm is unnecessary overhead.
   if (pattern_length == 1) {
     AssertNoAllocation no_heap_allocation;  // ensure vectors stay valid
-    if (StringShape(*sub).IsAsciiRepresentation()) {
+    if (sub->IsAsciiRepresentation()) {
       uc16 pchar = pat->Get(0);
       if (pchar > String::kMaxAsciiCharCode) {
         return -1;
@@ -2190,15 +2190,15 @@
 
   AssertNoAllocation no_heap_allocation;  // ensure vectors stay valid
   // dispatch on type of strings
-  if (StringShape(*pat).IsAsciiRepresentation()) {
+  if (pat->IsAsciiRepresentation()) {
     Vector<const char> pat_vector = pat->ToAsciiVector();
-    if (StringShape(*sub).IsAsciiRepresentation()) {
+    if (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 (StringShape(*sub).IsAsciiRepresentation()) {
+  if (sub->IsAsciiRepresentation()) {
     return StringMatchStrategy(sub->ToAsciiVector(), pat_vector, start_index);
   }
   return StringMatchStrategy(sub->ToUC16Vector(), pat_vector, start_index);
@@ -3329,7 +3329,7 @@
   // 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 = StringShape(s).IsAsciiRepresentation()
+  Object* o = s->IsAsciiRepresentation()
       ? Heap::AllocateRawAsciiString(length)
       : Heap::AllocateRawTwoByteString(length);
   if (o->IsFailure()) return o;
@@ -3680,7 +3680,7 @@
     if (first->IsString()) return first;
   }
 
-  bool ascii = StringShape(special).IsAsciiRepresentation();
+  bool ascii = special->IsAsciiRepresentation();
   int position = 0;
   for (int i = 0; i < array_length; i++) {
     Object* elt = fixed_array->get(i);
@@ -3700,7 +3700,7 @@
         return Failure::OutOfMemoryException();
       }
       position += element_length;
-      if (ascii && !StringShape(element).IsAsciiRepresentation()) {
+      if (ascii && !element->IsAsciiRepresentation()) {
         ascii = false;
       }
     } else {
@@ -4757,10 +4757,10 @@
   FixedArray* output_array = output->elements();
   RUNTIME_ASSERT(output_array->length() >= DateParser::OUTPUT_SIZE);
   bool result;
-  if (StringShape(*str).IsAsciiRepresentation()) {
+  if (str->IsAsciiRepresentation()) {
     result = DateParser::Parse(str->ToAsciiVector(), output_array);
   } else {
-    ASSERT(StringShape(*str).IsTwoByteRepresentation());
+    ASSERT(str->IsTwoByteRepresentation());
     result = DateParser::Parse(str->ToUC16Vector(), output_array);
   }
 
@@ -5244,12 +5244,16 @@
   return string;
 }
 
-
+// Moves all own elements of an object, that are below a limit, to positions
+// starting at zero. All undefined values are placed after non-undefined values,
+// and are followed by non-existing element. Does not change the length
+// property.
+// Returns the number of non-undefined elements collected.
 static Object* Runtime_RemoveArrayHoles(Arguments args) {
-  ASSERT(args.length() == 1);
-  // Ignore the case if this is not a JSArray.
-  if (!args[0]->IsJSArray()) return args[0];
-  return JSArray::cast(args[0])->RemoveHoles();
+  ASSERT(args.length() == 2);
+  CONVERT_CHECKED(JSObject, object, args[0]);
+  CONVERT_NUMBER_CHECKED(uint32_t, limit, Uint32, args[1]);
+  return object->PrepareElementsForSort(limit);
 }
 
 
@@ -5285,8 +5289,7 @@
 static Object* Runtime_GetArrayKeys(Arguments args) {
   ASSERT(args.length() == 2);
   HandleScope scope;
-  CONVERT_CHECKED(JSArray, raw_array, args[0]);
-  Handle<JSArray> array(raw_array);
+  CONVERT_ARG_CHECKED(JSObject, array, 0);
   CONVERT_NUMBER_CHECKED(uint32_t, length, Uint32, args[1]);
   if (array->elements()->IsDictionary()) {
     // Create an array and get all the keys into it, then remove all the
@@ -5308,8 +5311,10 @@
     single_interval->set(0,
                          Smi::FromInt(-1),
                          SKIP_WRITE_BARRIER);
+    uint32_t actual_length = static_cast<uint32_t>(array->elements()->length());
+    uint32_t min_length = actual_length < length ? actual_length : length;
     Handle<Object> length_object =
-        Factory::NewNumber(static_cast<double>(length));
+        Factory::NewNumber(static_cast<double>(min_length));
     single_interval->set(1, *length_object);
     return *Factory::NewJSArrayWithElements(single_interval);
   }
@@ -6569,9 +6574,9 @@
   if (!str->IsString() || !StringShape(String::cast(str)).IsExternal()) {
     return true;
   }
-  if (StringShape(String::cast(str)).IsAsciiRepresentation()) {
+  if (String::cast(str)->IsAsciiRepresentation()) {
     return ExternalAsciiString::cast(str)->resource() != NULL;
-  } else if (StringShape(String::cast(str)).IsTwoByteRepresentation()) {
+  } else if (String::cast(str)->IsTwoByteRepresentation()) {
     return ExternalTwoByteString::cast(str)->resource() != NULL;
   } else {
     return true;