Optimized String.prototype.match.

Improved the stack information in profiles.

Fixed bug in ARM port making it possible to compile the runtime system for thumb mode again.

Implemented a number of optimizations in the code generator.

Fixed a number of memory leaks in tests.

Fixed crash bug in connection with script source code and external strings.



git-svn-id: http://v8.googlecode.com/svn/trunk@1642 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/src/runtime.cc b/src/runtime.cc
index 38db689..5962b2a 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -1038,7 +1038,9 @@
   CONVERT_CHECKED(Smi, index, args[2]);
   CONVERT_CHECKED(JSArray, raw_last_match_info, args[3]);
   Handle<JSArray> last_match_info(raw_last_match_info);
-  CHECK(last_match_info->HasFastElements());
+  RUNTIME_ASSERT(last_match_info->HasFastElements());
+  RUNTIME_ASSERT(index->value() >= 0);
+  RUNTIME_ASSERT(index->value() <= subject->length());
   Handle<Object> result = RegExpImpl::Exec(regexp,
                                            subject,
                                            index->value(),
@@ -1048,23 +1050,6 @@
 }
 
 
-static Object* Runtime_RegExpExecGlobal(Arguments args) {
-  HandleScope scope;
-  ASSERT(args.length() == 3);
-  CONVERT_CHECKED(JSRegExp, raw_regexp, args[0]);
-  Handle<JSRegExp> regexp(raw_regexp);
-  CONVERT_CHECKED(String, raw_subject, args[1]);
-  Handle<String> subject(raw_subject);
-  CONVERT_CHECKED(JSArray, raw_last_match_info, args[2]);
-  Handle<JSArray> last_match_info(raw_last_match_info);
-  CHECK(last_match_info->HasFastElements());
-  Handle<Object> result =
-      RegExpImpl::ExecGlobal(regexp, subject, last_match_info);
-  if (result.is_null()) return Failure::Exception();
-  return *result;
-}
-
-
 static Object* Runtime_MaterializeRegExpLiteral(Arguments args) {
   HandleScope scope;
   ASSERT(args.length() == 4);
@@ -2337,6 +2322,57 @@
 }
 
 
+static Object* Runtime_StringMatch(Arguments args) {
+  ASSERT_EQ(3, args.length());
+
+  CONVERT_ARG_CHECKED(String, subject, 0);
+  CONVERT_ARG_CHECKED(JSRegExp, regexp, 1);
+  CONVERT_ARG_CHECKED(JSArray, regexp_info, 2);
+  HandleScope handles;
+
+  Handle<Object> match = RegExpImpl::Exec(regexp, subject, 0, regexp_info);
+
+  if (match.is_null()) {
+    return Failure::Exception();
+  }
+  if (match->IsNull()) {
+    return Heap::null_value();
+  }
+  int length = subject->length();
+
+  ZoneScope zone_space(DELETE_ON_EXIT);
+  ZoneList<int> offsets(8);
+  do {
+    int start;
+    int end;
+    {
+      AssertNoAllocation no_alloc;
+      FixedArray* elements = regexp_info->elements();
+      start = Smi::cast(elements->get(RegExpImpl::kFirstCapture))->value();
+      end = Smi::cast(elements->get(RegExpImpl::kFirstCapture + 1))->value();
+    }
+    offsets.Add(start);
+    offsets.Add(end);
+    int index = start < end ? end : end + 1;
+    if (index > length) break;
+    match = RegExpImpl::Exec(regexp, subject, index, regexp_info);
+    if (match.is_null()) {
+      return Failure::Exception();
+    }
+  } while (!match->IsNull());
+  int matches = offsets.length() / 2;
+  Handle<FixedArray> elements = Factory::NewFixedArray(matches);
+  for (int i = 0; i < matches ; i++) {
+    int from = offsets.at(i * 2);
+    int to = offsets.at(i * 2 + 1);
+    elements->set(i, *Factory::NewStringSlice(subject, from, to));
+  }
+  Handle<JSArray> result = Factory::NewJSArrayWithElements(elements);
+  result->set_length(Smi::FromInt(matches));
+  return *result;
+}
+
+
 static Object* Runtime_NumberToRadixString(Arguments args) {
   NoHandleAllocation ha;
   ASSERT(args.length() == 2);
@@ -6473,6 +6509,22 @@
 }
 
 
+// If an object given is an external string, check that the underlying
+// resource is accessible. For other kinds of objects, always return true.
+static bool IsExternalStringValid(Object* str) {
+  if (!str->IsString() || !StringShape(String::cast(str)).IsExternal()) {
+    return true;
+  }
+  if (StringShape(String::cast(str)).IsAsciiRepresentation()) {
+    return ExternalAsciiString::cast(str)->resource() != 0;
+  } else if (StringShape(String::cast(str)).IsTwoByteRepresentation()) {
+    return ExternalTwoByteString::cast(str)->resource() != 0;
+  } else {
+    return true;
+  }
+}
+
+
 // Helper function used by Runtime_DebugGetLoadedScripts below.
 static int DebugGetLoadedScripts(FixedArray* instances, int instances_size) {
   NoHandleAllocation ha;
@@ -6484,7 +6536,7 @@
   while (iterator.has_next()) {
     HeapObject* obj = iterator.next();
     ASSERT(obj != NULL);
-    if (obj->IsScript()) {
+    if (obj->IsScript() && IsExternalStringValid(Script::cast(obj)->source())) {
       if (instances != NULL && count < instances_size) {
         instances->set(count, obj);
       }