OLD | NEW |
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 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 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
288 // from the source pattern. | 288 // from the source pattern. |
289 // If compilation fails, an exception is thrown and this function | 289 // If compilation fails, an exception is thrown and this function |
290 // returns false. | 290 // returns false. |
291 bool RegExpImpl::EnsureCompiledIrregexp(Handle<JSRegExp> re, bool is_ascii) { | 291 bool RegExpImpl::EnsureCompiledIrregexp(Handle<JSRegExp> re, bool is_ascii) { |
292 Object* compiled_code = re->DataAt(JSRegExp::code_index(is_ascii)); | 292 Object* compiled_code = re->DataAt(JSRegExp::code_index(is_ascii)); |
293 #ifdef V8_INTERPRETED_REGEXP | 293 #ifdef V8_INTERPRETED_REGEXP |
294 if (compiled_code->IsByteArray()) return true; | 294 if (compiled_code->IsByteArray()) return true; |
295 #else // V8_INTERPRETED_REGEXP (RegExp native code) | 295 #else // V8_INTERPRETED_REGEXP (RegExp native code) |
296 if (compiled_code->IsCode()) return true; | 296 if (compiled_code->IsCode()) return true; |
297 #endif | 297 #endif |
| 298 // We could potentially have marked this as flushable, but have kept |
| 299 // a saved version if we did not flush it yet. |
| 300 Object* saved_code = re->DataAt(JSRegExp::saved_code_index(is_ascii)); |
| 301 if (saved_code->IsCode()) { |
| 302 // Reinstate the code in the original place. |
| 303 re->SetDataAt(JSRegExp::code_index(is_ascii), saved_code); |
| 304 ASSERT(compiled_code->IsSmi()); |
| 305 return true; |
| 306 } |
298 return CompileIrregexp(re, is_ascii); | 307 return CompileIrregexp(re, is_ascii); |
299 } | 308 } |
300 | 309 |
301 | 310 |
| 311 static bool CreateRegExpErrorObjectAndThrow(Handle<JSRegExp> re, |
| 312 bool is_ascii, |
| 313 Handle<String> error_message, |
| 314 Isolate* isolate) { |
| 315 Factory* factory = isolate->factory(); |
| 316 Handle<FixedArray> elements = factory->NewFixedArray(2); |
| 317 elements->set(0, re->Pattern()); |
| 318 elements->set(1, *error_message); |
| 319 Handle<JSArray> array = factory->NewJSArrayWithElements(elements); |
| 320 Handle<Object> regexp_err = |
| 321 factory->NewSyntaxError("malformed_regexp", array); |
| 322 isolate->Throw(*regexp_err); |
| 323 return false; |
| 324 } |
| 325 |
| 326 |
302 bool RegExpImpl::CompileIrregexp(Handle<JSRegExp> re, bool is_ascii) { | 327 bool RegExpImpl::CompileIrregexp(Handle<JSRegExp> re, bool is_ascii) { |
303 // Compile the RegExp. | 328 // Compile the RegExp. |
304 Isolate* isolate = re->GetIsolate(); | 329 Isolate* isolate = re->GetIsolate(); |
305 ZoneScope zone_scope(isolate, DELETE_ON_EXIT); | 330 ZoneScope zone_scope(isolate, DELETE_ON_EXIT); |
306 PostponeInterruptsScope postpone(isolate); | 331 PostponeInterruptsScope postpone(isolate); |
| 332 // If we had a compilation error the last time this is saved at the |
| 333 // saved code index. |
307 Object* entry = re->DataAt(JSRegExp::code_index(is_ascii)); | 334 Object* entry = re->DataAt(JSRegExp::code_index(is_ascii)); |
308 if (entry->IsJSObject()) { | 335 // When arriving here entry can only be a smi, either representing an |
309 // If it's a JSObject, a previous compilation failed and threw this object. | 336 // uncompiled regexp, a previous compilation error, or code that has |
310 // Re-throw the object without trying again. | 337 // been flushed. |
311 isolate->Throw(entry); | 338 ASSERT(entry->IsSmi()); |
| 339 int entry_value = Smi::cast(entry)->value(); |
| 340 ASSERT(entry_value == JSRegExp::kUninitializedValue || |
| 341 entry_value == JSRegExp::kCompilationErrorValue || |
| 342 (entry_value < JSRegExp::kCodeAgeMask && entry_value >= 0)); |
| 343 |
| 344 if (entry_value == JSRegExp::kCompilationErrorValue) { |
| 345 // A previous compilation failed and threw an error which we store in |
| 346 // the saved code index (we store the error message, not the actual |
| 347 // error). Recreate the error object and throw it. |
| 348 Object* error_string = re->DataAt(JSRegExp::saved_code_index(is_ascii)); |
| 349 ASSERT(error_string->IsString()); |
| 350 Handle<String> error_message(String::cast(error_string)); |
| 351 CreateRegExpErrorObjectAndThrow(re, is_ascii, error_message, isolate); |
312 return false; | 352 return false; |
313 } | 353 } |
314 ASSERT(entry->IsTheHole()); | |
315 | 354 |
316 JSRegExp::Flags flags = re->GetFlags(); | 355 JSRegExp::Flags flags = re->GetFlags(); |
317 | 356 |
318 Handle<String> pattern(re->Pattern()); | 357 Handle<String> pattern(re->Pattern()); |
319 if (!pattern->IsFlat()) { | 358 if (!pattern->IsFlat()) { |
320 FlattenString(pattern); | 359 FlattenString(pattern); |
321 } | 360 } |
322 | 361 |
323 RegExpCompileData compile_data; | 362 RegExpCompileData compile_data; |
324 FlatStringReader reader(isolate, pattern); | 363 FlatStringReader reader(isolate, pattern); |
325 if (!RegExpParser::ParseRegExp(&reader, flags.is_multiline(), | 364 if (!RegExpParser::ParseRegExp(&reader, flags.is_multiline(), |
326 &compile_data)) { | 365 &compile_data)) { |
327 // Throw an exception if we fail to parse the pattern. | 366 // Throw an exception if we fail to parse the pattern. |
328 // THIS SHOULD NOT HAPPEN. We already pre-parsed it successfully once. | 367 // THIS SHOULD NOT HAPPEN. We already pre-parsed it successfully once. |
329 ThrowRegExpException(re, | 368 ThrowRegExpException(re, |
330 pattern, | 369 pattern, |
331 compile_data.error, | 370 compile_data.error, |
332 "malformed_regexp"); | 371 "malformed_regexp"); |
333 return false; | 372 return false; |
334 } | 373 } |
335 RegExpEngine::CompilationResult result = | 374 RegExpEngine::CompilationResult result = |
336 RegExpEngine::Compile(&compile_data, | 375 RegExpEngine::Compile(&compile_data, |
337 flags.is_ignore_case(), | 376 flags.is_ignore_case(), |
338 flags.is_multiline(), | 377 flags.is_multiline(), |
339 pattern, | 378 pattern, |
340 is_ascii); | 379 is_ascii); |
341 if (result.error_message != NULL) { | 380 if (result.error_message != NULL) { |
342 // Unable to compile regexp. | 381 // Unable to compile regexp. |
343 Factory* factory = isolate->factory(); | |
344 Handle<FixedArray> elements = factory->NewFixedArray(2); | |
345 elements->set(0, *pattern); | |
346 Handle<String> error_message = | 382 Handle<String> error_message = |
347 factory->NewStringFromUtf8(CStrVector(result.error_message)); | 383 isolate->factory()->NewStringFromUtf8(CStrVector(result.error_message)); |
348 elements->set(1, *error_message); | 384 CreateRegExpErrorObjectAndThrow(re, is_ascii, error_message, isolate); |
349 Handle<JSArray> array = factory->NewJSArrayWithElements(elements); | |
350 Handle<Object> regexp_err = | |
351 factory->NewSyntaxError("malformed_regexp", array); | |
352 isolate->Throw(*regexp_err); | |
353 re->SetDataAt(JSRegExp::code_index(is_ascii), *regexp_err); | |
354 return false; | 385 return false; |
355 } | 386 } |
356 | 387 |
357 Handle<FixedArray> data = Handle<FixedArray>(FixedArray::cast(re->data())); | 388 Handle<FixedArray> data = Handle<FixedArray>(FixedArray::cast(re->data())); |
358 data->set(JSRegExp::code_index(is_ascii), result.code); | 389 data->set(JSRegExp::code_index(is_ascii), result.code); |
359 int register_max = IrregexpMaxRegisterCount(*data); | 390 int register_max = IrregexpMaxRegisterCount(*data); |
360 if (result.num_registers > register_max) { | 391 if (result.num_registers > register_max) { |
361 SetIrregexpMaxRegisterCount(*data, result.num_registers); | 392 SetIrregexpMaxRegisterCount(*data, result.num_registers); |
362 } | 393 } |
363 | 394 |
(...skipping 4967 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5331 } | 5362 } |
5332 | 5363 |
5333 return compiler.Assemble(¯o_assembler, | 5364 return compiler.Assemble(¯o_assembler, |
5334 node, | 5365 node, |
5335 data->capture_count, | 5366 data->capture_count, |
5336 pattern); | 5367 pattern); |
5337 } | 5368 } |
5338 | 5369 |
5339 | 5370 |
5340 }} // namespace v8::internal | 5371 }} // namespace v8::internal |
OLD | NEW |