| OLD | NEW |
| 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 14 matching lines...) Expand all Loading... |
| 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 | 27 |
| 28 #include "v8.h" | 28 #include "v8.h" |
| 29 | 29 |
| 30 #include "execution.h" | 30 #include "execution.h" |
| 31 #include "factory.h" | 31 #include "factory.h" |
| 32 #include "jsregexp.h" | 32 #include "jsregexp.h" |
| 33 #include "third_party/jscre/pcre.h" | 33 #include "third_party/jscre/pcre.h" |
| 34 #include "platform.h" | 34 #include "platform.h" |
| 35 #include "runtime.h" |
| 35 #include "top.h" | 36 #include "top.h" |
| 36 | 37 |
| 37 namespace v8 { namespace internal { | 38 namespace v8 { namespace internal { |
| 38 | 39 |
| 39 | 40 |
| 40 #define CAPTURE_INDEX 0 | 41 #define CAPTURE_INDEX 0 |
| 41 #define INTERNAL_INDEX 1 | 42 #define INTERNAL_INDEX 1 |
| 42 | 43 |
| 43 static Failure* malloc_failure; | 44 static Failure* malloc_failure; |
| 44 | 45 |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 135 Factory::NewRawTwoByteString(flat_string->length(), TENURED); | 136 Factory::NewRawTwoByteString(flat_string->length(), TENURED); |
| 136 static StringInputBuffer convert_to_two_byte_buffer; | 137 static StringInputBuffer convert_to_two_byte_buffer; |
| 137 convert_to_two_byte_buffer.Reset(*flat_string); | 138 convert_to_two_byte_buffer.Reset(*flat_string); |
| 138 for (int i = 0; convert_to_two_byte_buffer.has_more(); i++) { | 139 for (int i = 0; convert_to_two_byte_buffer.has_more(); i++) { |
| 139 two_byte_string->Set(i, convert_to_two_byte_buffer.GetNext()); | 140 two_byte_string->Set(i, convert_to_two_byte_buffer.GetNext()); |
| 140 } | 141 } |
| 141 return two_byte_string; | 142 return two_byte_string; |
| 142 } | 143 } |
| 143 | 144 |
| 144 | 145 |
| 146 unibrow::Predicate<unibrow::RegExpSpecialChar, 128> is_reg_exp_special_char; |
| 147 |
| 148 |
| 149 Handle<Object> RegExpImpl::Compile(Handle<JSRegExp> re, |
| 150 Handle<String> pattern, |
| 151 Handle<String> flags) { |
| 152 bool is_atom = true; |
| 153 for (int i = 0; is_atom && i < flags->length(); i++) { |
| 154 if (flags->Get(i) == 'i') |
| 155 is_atom = false; |
| 156 } |
| 157 for (int i = 0; is_atom && i < pattern->length(); i++) { |
| 158 if (is_reg_exp_special_char.get(pattern->Get(i))) |
| 159 is_atom = false; |
| 160 } |
| 161 Handle<Object> result; |
| 162 if (is_atom) { |
| 163 result = AtomCompile(re, pattern); |
| 164 } else { |
| 165 result = JsreCompile(re, pattern, flags); |
| 166 } |
| 167 |
| 168 LOG(RegExpCompileEvent(re)); |
| 169 return result; |
| 170 } |
| 171 |
| 172 |
| 173 Handle<Object> RegExpImpl::Exec(Handle<JSRegExp> regexp, |
| 174 Handle<String> subject, |
| 175 Handle<Object> index) { |
| 176 switch (regexp->type_tag()) { |
| 177 case JSRegExp::JSCRE: |
| 178 return JsreExec(regexp, subject, index); |
| 179 case JSRegExp::ATOM: |
| 180 return AtomExec(regexp, subject, index); |
| 181 default: |
| 182 UNREACHABLE(); |
| 183 return Handle<Object>(); |
| 184 } |
| 185 } |
| 186 |
| 187 |
| 188 Handle<Object> RegExpImpl::ExecGlobal(Handle<JSRegExp> regexp, |
| 189 Handle<String> subject) { |
| 190 switch (regexp->type_tag()) { |
| 191 case JSRegExp::JSCRE: |
| 192 return JsreExecGlobal(regexp, subject); |
| 193 case JSRegExp::ATOM: |
| 194 return AtomExecGlobal(regexp, subject); |
| 195 default: |
| 196 UNREACHABLE(); |
| 197 return Handle<Object>(); |
| 198 } |
| 199 } |
| 200 |
| 201 |
| 202 Handle<Object> RegExpImpl::AtomCompile(Handle<JSRegExp> re, |
| 203 Handle<String> pattern) { |
| 204 re->set_type_tag(JSRegExp::ATOM); |
| 205 re->set_data(*pattern); |
| 206 return re; |
| 207 } |
| 208 |
| 209 |
| 210 Handle<Object> RegExpImpl::AtomExec(Handle<JSRegExp> re, |
| 211 Handle<String> subject, |
| 212 Handle<Object> index) { |
| 213 Handle<String> needle(String::cast(re->data())); |
| 214 |
| 215 uint32_t start_index; |
| 216 if (!Array::IndexFromObject(*index, &start_index)) { |
| 217 return Handle<Smi>(Smi::FromInt(-1)); |
| 218 } |
| 219 |
| 220 LOG(RegExpExecEvent(re, start_index, subject)); |
| 221 int value = Runtime::StringMatchKmp(*subject, *needle, start_index); |
| 222 if (value == -1) return Factory::null_value(); |
| 223 Handle<JSArray> result = Factory::NewJSArray(2); |
| 224 SetElement(result, 0, Handle<Smi>(Smi::FromInt(value))); |
| 225 SetElement(result, 1, Handle<Smi>(Smi::FromInt(value + needle->length()))); |
| 226 return result; |
| 227 } |
| 228 |
| 229 |
| 230 Handle<Object> RegExpImpl::AtomExecGlobal(Handle<JSRegExp> re, |
| 231 Handle<String> subject) { |
| 232 Handle<String> needle(String::cast(re->data())); |
| 233 Handle<JSArray> result = Factory::NewJSArray(1); |
| 234 bool keep_going = true; |
| 235 int index = 0; |
| 236 int match_count = 0; |
| 237 int needle_length = needle->length(); |
| 238 while (keep_going) { |
| 239 LOG(RegExpExecEvent(re, index, subject)); |
| 240 int value = Runtime::StringMatchKmp(*subject, *needle, index); |
| 241 if (value == -1) break; |
| 242 HandleScope scope; |
| 243 int end = value + needle_length; |
| 244 Handle<JSArray> pair = Factory::NewJSArray(2); |
| 245 SetElement(pair, 0, Handle<Smi>(Smi::FromInt(value))); |
| 246 SetElement(pair, 1, Handle<Smi>(Smi::FromInt(end))); |
| 247 SetElement(result, match_count, pair); |
| 248 match_count++; |
| 249 index = end; |
| 250 if (needle_length == 0) |
| 251 index++; |
| 252 } |
| 253 return result; |
| 254 } |
| 255 |
| 256 |
| 145 Handle<Object> RegExpImpl::JsreCompile(Handle<JSRegExp> re, | 257 Handle<Object> RegExpImpl::JsreCompile(Handle<JSRegExp> re, |
| 146 Handle<String> pattern, | 258 Handle<String> pattern, |
| 147 Handle<String> flags) { | 259 Handle<String> flags) { |
| 148 JSRegExpIgnoreCaseOption case_option = JSRegExpDoNotIgnoreCase; | 260 JSRegExpIgnoreCaseOption case_option = JSRegExpDoNotIgnoreCase; |
| 149 JSRegExpMultilineOption multiline_option = JSRegExpSingleLine; | 261 JSRegExpMultilineOption multiline_option = JSRegExpSingleLine; |
| 150 FlattenString(flags); | 262 FlattenString(flags); |
| 151 for (int i = 0; i < flags->length(); i++) { | 263 for (int i = 0; i < flags->length(); i++) { |
| 152 if (flags->Get(i) == 'i') case_option = JSRegExpIgnoreCase; | 264 if (flags->Get(i) == 'i') case_option = JSRegExpIgnoreCase; |
| 153 if (flags->Get(i) == 'm') multiline_option = JSRegExpMultiline; | 265 if (flags->Get(i) == 'm') multiline_option = JSRegExpMultiline; |
| 154 } | 266 } |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 199 // Convert the return address to a ByteArray pointer. | 311 // Convert the return address to a ByteArray pointer. |
| 200 Handle<ByteArray> internal( | 312 Handle<ByteArray> internal( |
| 201 ByteArray::FromDataStartAddress(reinterpret_cast<Address>(code))); | 313 ByteArray::FromDataStartAddress(reinterpret_cast<Address>(code))); |
| 202 | 314 |
| 203 Handle<FixedArray> value = Factory::NewFixedArray(2); | 315 Handle<FixedArray> value = Factory::NewFixedArray(2); |
| 204 value->set(CAPTURE_INDEX, Smi::FromInt(number_of_captures)); | 316 value->set(CAPTURE_INDEX, Smi::FromInt(number_of_captures)); |
| 205 value->set(INTERNAL_INDEX, *internal); | 317 value->set(INTERNAL_INDEX, *internal); |
| 206 re->set_type_tag(JSRegExp::JSCRE); | 318 re->set_type_tag(JSRegExp::JSCRE); |
| 207 re->set_data(*value); | 319 re->set_data(*value); |
| 208 | 320 |
| 209 LOG(RegExpCompileEvent(re)); | |
| 210 | |
| 211 return re; | 321 return re; |
| 212 } | 322 } |
| 213 | 323 |
| 214 | 324 |
| 215 Handle<Object> RegExpImpl::JsreExecOnce(Handle<JSRegExp> regexp, | 325 Handle<Object> RegExpImpl::JsreExecOnce(Handle<JSRegExp> regexp, |
| 216 int num_captures, | 326 int num_captures, |
| 217 Handle<String> subject, | 327 Handle<String> subject, |
| 218 int previous_index, | 328 int previous_index, |
| 219 const uc16* two_byte_subject, | 329 const uc16* two_byte_subject, |
| 220 int* offsets_vector, | 330 int* offsets_vector, |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 253 return Handle<Object>(Top::Throw(*regexp_err)); | 363 return Handle<Object>(Top::Throw(*regexp_err)); |
| 254 } | 364 } |
| 255 | 365 |
| 256 Handle<JSArray> result = Factory::NewJSArray(2 * (num_captures+1)); | 366 Handle<JSArray> result = Factory::NewJSArray(2 * (num_captures+1)); |
| 257 | 367 |
| 258 // The captures come in (start, end+1) pairs. | 368 // The captures come in (start, end+1) pairs. |
| 259 for (int i = 0; i < 2 * (num_captures+1); i += 2) { | 369 for (int i = 0; i < 2 * (num_captures+1); i += 2) { |
| 260 SetElement(result, i, Handle<Object>(Smi::FromInt(offsets_vector[i]))); | 370 SetElement(result, i, Handle<Object>(Smi::FromInt(offsets_vector[i]))); |
| 261 SetElement(result, i+1, Handle<Object>(Smi::FromInt(offsets_vector[i+1]))); | 371 SetElement(result, i+1, Handle<Object>(Smi::FromInt(offsets_vector[i+1]))); |
| 262 } | 372 } |
| 263 | |
| 264 return result; | 373 return result; |
| 265 } | 374 } |
| 266 | 375 |
| 267 | 376 |
| 268 class OffsetsVector { | 377 class OffsetsVector { |
| 269 public: | 378 public: |
| 270 inline OffsetsVector(int num_captures) { | 379 inline OffsetsVector(int num_captures) { |
| 271 offsets_vector_length_ = (num_captures + 1) * 3; | 380 offsets_vector_length_ = (num_captures + 1) * 3; |
| 272 if (offsets_vector_length_ > kStaticOffsetsVectorSize) { | 381 if (offsets_vector_length_ > kStaticOffsetsVectorSize) { |
| 273 vector_ = NewArray<int>(offsets_vector_length_); | 382 vector_ = NewArray<int>(offsets_vector_length_); |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 379 } | 488 } |
| 380 | 489 |
| 381 | 490 |
| 382 ByteArray* RegExpImpl::JsreInternal(Handle<JSRegExp> re) { | 491 ByteArray* RegExpImpl::JsreInternal(Handle<JSRegExp> re) { |
| 383 Object* value = re->data(); | 492 Object* value = re->data(); |
| 384 ASSERT(value->IsFixedArray()); | 493 ASSERT(value->IsFixedArray()); |
| 385 return ByteArray::cast(FixedArray::cast(value)->get(INTERNAL_INDEX)); | 494 return ByteArray::cast(FixedArray::cast(value)->get(INTERNAL_INDEX)); |
| 386 } | 495 } |
| 387 | 496 |
| 388 }} // namespace v8::internal | 497 }} // namespace v8::internal |
| OLD | NEW |