| 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 2435 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2446 | 2446 |
| 2447 void DotPrinter::PrintAttributes(RegExpNode* that) { | 2447 void DotPrinter::PrintAttributes(RegExpNode* that) { |
| 2448 stream()->Add(" a%p [shape=Mrecord, color=grey, fontcolor=grey, " | 2448 stream()->Add(" a%p [shape=Mrecord, color=grey, fontcolor=grey, " |
| 2449 "margin=0.1, fontsize=10, label=\"{", | 2449 "margin=0.1, fontsize=10, label=\"{", |
| 2450 that); | 2450 that); |
| 2451 AttributePrinter printer(this); | 2451 AttributePrinter printer(this); |
| 2452 NodeInfo* info = that->info(); | 2452 NodeInfo* info = that->info(); |
| 2453 printer.PrintBit("NI", info->follows_newline_interest); | 2453 printer.PrintBit("NI", info->follows_newline_interest); |
| 2454 printer.PrintBit("WI", info->follows_word_interest); | 2454 printer.PrintBit("WI", info->follows_word_interest); |
| 2455 printer.PrintBit("SI", info->follows_start_interest); | 2455 printer.PrintBit("SI", info->follows_start_interest); |
| 2456 printer.PrintBit("DN", info->determine_newline); | |
| 2457 printer.PrintBit("DW", info->determine_word); | |
| 2458 printer.PrintBit("DS", info->determine_start); | |
| 2459 printer.PrintBit("DDN", info->does_determine_newline); | |
| 2460 printer.PrintBit("DDW", info->does_determine_word); | |
| 2461 printer.PrintBit("DDS", info->does_determine_start); | |
| 2462 printer.PrintPositive("IW", info->is_word); | |
| 2463 printer.PrintPositive("IN", info->is_newline); | |
| 2464 printer.PrintPositive("FN", info->follows_newline); | |
| 2465 printer.PrintPositive("FW", info->follows_word); | |
| 2466 printer.PrintPositive("FS", info->follows_start); | |
| 2467 Label* label = that->label(); | 2456 Label* label = that->label(); |
| 2468 if (label->is_bound()) | 2457 if (label->is_bound()) |
| 2469 printer.PrintPositive("@", label->pos()); | 2458 printer.PrintPositive("@", label->pos()); |
| 2470 stream()->Add("}\"];\n"); | 2459 stream()->Add("}\"];\n"); |
| 2471 stream()->Add(" a%p -> n%p [style=dashed, color=grey, " | 2460 stream()->Add(" a%p -> n%p [style=dashed, color=grey, " |
| 2472 "arrowhead=none];\n", that, that); | 2461 "arrowhead=none];\n", that, that); |
| 2473 } | 2462 } |
| 2474 | 2463 |
| 2475 | 2464 |
| 2476 static const bool kPrintDispatchTable = false; | 2465 static const bool kPrintDispatchTable = false; |
| (...skipping 591 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3068 RegExpNode* sibling = siblings_.Get(i); | 3057 RegExpNode* sibling = siblings_.Get(i); |
| 3069 if (sibling->info()->Matches(info)) | 3058 if (sibling->info()->Matches(info)) |
| 3070 return sibling; | 3059 return sibling; |
| 3071 } | 3060 } |
| 3072 return NULL; | 3061 return NULL; |
| 3073 } | 3062 } |
| 3074 | 3063 |
| 3075 | 3064 |
| 3076 RegExpNode* RegExpNode::EnsureSibling(NodeInfo* info, bool* cloned) { | 3065 RegExpNode* RegExpNode::EnsureSibling(NodeInfo* info, bool* cloned) { |
| 3077 ASSERT_EQ(false, *cloned); | 3066 ASSERT_EQ(false, *cloned); |
| 3078 ASSERT(!info->HasAssertions()); | |
| 3079 siblings_.Ensure(this); | 3067 siblings_.Ensure(this); |
| 3080 RegExpNode* result = TryGetSibling(info); | 3068 RegExpNode* result = TryGetSibling(info); |
| 3081 if (result != NULL) return result; | 3069 if (result != NULL) return result; |
| 3082 result = this->Clone(); | 3070 result = this->Clone(); |
| 3083 NodeInfo* new_info = result->info(); | 3071 NodeInfo* new_info = result->info(); |
| 3084 new_info->ResetCompilationState(); | 3072 new_info->ResetCompilationState(); |
| 3085 new_info->AddFromPreceding(info); | 3073 new_info->AddFromPreceding(info); |
| 3086 AddSibling(result); | 3074 AddSibling(result); |
| 3087 *cloned = true; | 3075 *cloned = true; |
| 3088 return result; | 3076 return result; |
| (...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3300 return entry->out_set(); | 3288 return entry->out_set(); |
| 3301 else | 3289 else |
| 3302 return empty(); | 3290 return empty(); |
| 3303 } | 3291 } |
| 3304 | 3292 |
| 3305 | 3293 |
| 3306 // ------------------------------------------------------------------- | 3294 // ------------------------------------------------------------------- |
| 3307 // Analysis | 3295 // Analysis |
| 3308 | 3296 |
| 3309 | 3297 |
| 3310 void AssertionPropagation::EnsureAnalyzed(RegExpNode* that) { | 3298 void Analysis::EnsureAnalyzed(RegExpNode* that) { |
| 3311 if (that->info()->been_analyzed || that->info()->being_analyzed) | 3299 if (that->info()->been_analyzed || that->info()->being_analyzed) |
| 3312 return; | 3300 return; |
| 3313 that->info()->being_analyzed = true; | 3301 that->info()->being_analyzed = true; |
| 3314 that->Accept(this); | 3302 that->Accept(this); |
| 3315 that->info()->being_analyzed = false; | 3303 that->info()->being_analyzed = false; |
| 3316 that->info()->been_analyzed = true; | 3304 that->info()->been_analyzed = true; |
| 3317 } | 3305 } |
| 3318 | 3306 |
| 3319 | 3307 |
| 3320 void AssertionPropagation::VisitEnd(EndNode* that) { | 3308 void Analysis::VisitEnd(EndNode* that) { |
| 3321 // nothing to do | 3309 // nothing to do |
| 3322 } | 3310 } |
| 3323 | 3311 |
| 3324 | 3312 |
| 3325 void TextNode::CalculateOffsets() { | 3313 void TextNode::CalculateOffsets() { |
| 3326 int element_count = elements()->length(); | 3314 int element_count = elements()->length(); |
| 3327 // Set up the offsets of the elements relative to the start. This is a fixed | 3315 // Set up the offsets of the elements relative to the start. This is a fixed |
| 3328 // quantity since a TextNode can only contain fixed-width things. | 3316 // quantity since a TextNode can only contain fixed-width things. |
| 3329 int cp_offset = 0; | 3317 int cp_offset = 0; |
| 3330 for (int i = 0; i < element_count; i++) { | 3318 for (int i = 0; i < element_count; i++) { |
| 3331 TextElement& elm = elements()->at(i); | 3319 TextElement& elm = elements()->at(i); |
| 3332 elm.cp_offset = cp_offset; | 3320 elm.cp_offset = cp_offset; |
| 3333 if (elm.type == TextElement::ATOM) { | 3321 if (elm.type == TextElement::ATOM) { |
| 3334 cp_offset += elm.data.u_atom->data().length(); | 3322 cp_offset += elm.data.u_atom->data().length(); |
| 3335 } else { | 3323 } else { |
| 3336 cp_offset++; | 3324 cp_offset++; |
| 3337 Vector<const uc16> quarks = elm.data.u_atom->data(); | 3325 Vector<const uc16> quarks = elm.data.u_atom->data(); |
| 3338 } | 3326 } |
| 3339 } | 3327 } |
| 3340 } | 3328 } |
| 3341 | 3329 |
| 3342 | 3330 |
| 3343 void AssertionPropagation::VisitText(TextNode* that) { | 3331 void Analysis::VisitText(TextNode* that) { |
| 3344 if (ignore_case_) { | 3332 if (ignore_case_) { |
| 3345 that->MakeCaseIndependent(); | 3333 that->MakeCaseIndependent(); |
| 3346 } | 3334 } |
| 3347 EnsureAnalyzed(that->on_success()); | 3335 EnsureAnalyzed(that->on_success()); |
| 3348 NodeInfo* info = that->info(); | |
| 3349 NodeInfo* next_info = that->on_success()->info(); | |
| 3350 // If the following node is interested in what it follows then this | |
| 3351 // node must determine it. | |
| 3352 info->determine_newline = next_info->follows_newline_interest; | |
| 3353 info->determine_word = next_info->follows_word_interest; | |
| 3354 info->determine_start = next_info->follows_start_interest; | |
| 3355 that->CalculateOffsets(); | 3336 that->CalculateOffsets(); |
| 3356 } | 3337 } |
| 3357 | 3338 |
| 3358 | 3339 |
| 3359 void AssertionPropagation::VisitAction(ActionNode* that) { | 3340 void Analysis::VisitAction(ActionNode* that) { |
| 3360 RegExpNode* target = that->on_success(); | 3341 RegExpNode* target = that->on_success(); |
| 3361 EnsureAnalyzed(target); | 3342 EnsureAnalyzed(target); |
| 3362 // If the next node is interested in what it follows then this node | 3343 // If the next node is interested in what it follows then this node |
| 3363 // has to be interested too so it can pass the information on. | 3344 // has to be interested too so it can pass the information on. |
| 3364 that->info()->AddFromFollowing(target->info()); | 3345 that->info()->AddFromFollowing(target->info()); |
| 3365 } | 3346 } |
| 3366 | 3347 |
| 3367 | 3348 |
| 3368 void AssertionPropagation::VisitChoice(ChoiceNode* that) { | 3349 void Analysis::VisitChoice(ChoiceNode* that) { |
| 3369 NodeInfo* info = that->info(); | 3350 NodeInfo* info = that->info(); |
| 3370 for (int i = 0; i < that->alternatives()->length(); i++) { | 3351 for (int i = 0; i < that->alternatives()->length(); i++) { |
| 3371 RegExpNode* node = that->alternatives()->at(i).node(); | 3352 RegExpNode* node = that->alternatives()->at(i).node(); |
| 3372 EnsureAnalyzed(node); | 3353 EnsureAnalyzed(node); |
| 3373 // Anything the following nodes need to know has to be known by | 3354 // Anything the following nodes need to know has to be known by |
| 3374 // this node also, so it can pass it on. | 3355 // this node also, so it can pass it on. |
| 3375 info->AddFromFollowing(node->info()); | 3356 info->AddFromFollowing(node->info()); |
| 3376 } | 3357 } |
| 3377 } | 3358 } |
| 3378 | 3359 |
| 3379 | 3360 |
| 3380 void AssertionPropagation::VisitLoopChoice(LoopChoiceNode* that) { | 3361 void Analysis::VisitLoopChoice(LoopChoiceNode* that) { |
| 3381 NodeInfo* info = that->info(); | 3362 NodeInfo* info = that->info(); |
| 3382 for (int i = 0; i < that->alternatives()->length(); i++) { | 3363 for (int i = 0; i < that->alternatives()->length(); i++) { |
| 3383 RegExpNode* node = that->alternatives()->at(i).node(); | 3364 RegExpNode* node = that->alternatives()->at(i).node(); |
| 3384 if (node != that->loop_node()) { | 3365 if (node != that->loop_node()) { |
| 3385 EnsureAnalyzed(node); | 3366 EnsureAnalyzed(node); |
| 3386 info->AddFromFollowing(node->info()); | 3367 info->AddFromFollowing(node->info()); |
| 3387 } | 3368 } |
| 3388 } | 3369 } |
| 3389 // Check the loop last since it may need the value of this node | 3370 // Check the loop last since it may need the value of this node |
| 3390 // to get a correct result. | 3371 // to get a correct result. |
| 3391 EnsureAnalyzed(that->loop_node()); | 3372 EnsureAnalyzed(that->loop_node()); |
| 3392 info->AddFromFollowing(that->loop_node()->info()); | 3373 info->AddFromFollowing(that->loop_node()->info()); |
| 3393 } | 3374 } |
| 3394 | 3375 |
| 3395 | 3376 |
| 3396 void AssertionPropagation::VisitBackReference(BackReferenceNode* that) { | 3377 void Analysis::VisitBackReference(BackReferenceNode* that) { |
| 3397 EnsureAnalyzed(that->on_success()); | 3378 EnsureAnalyzed(that->on_success()); |
| 3398 } | 3379 } |
| 3399 | 3380 |
| 3400 | 3381 |
| 3401 // ------------------------------------------------------------------- | 3382 // ------------------------------------------------------------------- |
| 3402 // Assumption expansion | |
| 3403 | |
| 3404 | |
| 3405 RegExpNode* RegExpNode::EnsureExpanded(NodeInfo* info) { | |
| 3406 siblings_.Ensure(this); | |
| 3407 NodeInfo new_info = *this->info(); | |
| 3408 if (new_info.follows_word_interest) | |
| 3409 new_info.follows_word = info->follows_word; | |
| 3410 if (new_info.follows_newline_interest) | |
| 3411 new_info.follows_newline = info->follows_newline; | |
| 3412 // If the following node should determine something we need to get | |
| 3413 // a sibling that determines it. | |
| 3414 new_info.does_determine_newline = new_info.determine_newline; | |
| 3415 new_info.does_determine_word = new_info.determine_word; | |
| 3416 new_info.does_determine_start = new_info.determine_start; | |
| 3417 RegExpNode* sibling = TryGetSibling(&new_info); | |
| 3418 if (sibling == NULL) { | |
| 3419 sibling = ExpandLocal(&new_info); | |
| 3420 siblings_.Add(sibling); | |
| 3421 sibling->info()->being_expanded = true; | |
| 3422 sibling->ExpandChildren(); | |
| 3423 sibling->info()->being_expanded = false; | |
| 3424 sibling->info()->been_expanded = true; | |
| 3425 } else { | |
| 3426 NodeInfo* sib_info = sibling->info(); | |
| 3427 if (!sib_info->been_expanded && !sib_info->being_expanded) { | |
| 3428 sibling->info()->being_expanded = true; | |
| 3429 sibling->ExpandChildren(); | |
| 3430 sibling->info()->being_expanded = false; | |
| 3431 sibling->info()->been_expanded = true; | |
| 3432 } | |
| 3433 } | |
| 3434 return sibling; | |
| 3435 } | |
| 3436 | |
| 3437 | |
| 3438 RegExpNode* ChoiceNode::ExpandLocal(NodeInfo* info) { | |
| 3439 ChoiceNode* clone = this->Clone(); | |
| 3440 clone->info()->ResetCompilationState(); | |
| 3441 clone->info()->AddAssumptions(info); | |
| 3442 return clone; | |
| 3443 } | |
| 3444 | |
| 3445 | |
| 3446 void ChoiceNode::ExpandChildren() { | |
| 3447 ZoneList<GuardedAlternative>* alts = alternatives(); | |
| 3448 ZoneList<GuardedAlternative>* new_alts | |
| 3449 = new ZoneList<GuardedAlternative>(alts->length()); | |
| 3450 for (int i = 0; i < alts->length(); i++) { | |
| 3451 GuardedAlternative next = alts->at(i); | |
| 3452 next.set_node(next.node()->EnsureExpanded(info())); | |
| 3453 new_alts->Add(next); | |
| 3454 } | |
| 3455 alternatives_ = new_alts; | |
| 3456 } | |
| 3457 | |
| 3458 | |
| 3459 RegExpNode* TextNode::ExpandLocal(NodeInfo* info) { | |
| 3460 TextElement last = elements()->last(); | |
| 3461 if (last.type == TextElement::CHAR_CLASS) { | |
| 3462 RegExpCharacterClass* char_class = last.data.u_char_class; | |
| 3463 if (info->does_determine_word) { | |
| 3464 ZoneList<CharacterRange>* word = NULL; | |
| 3465 ZoneList<CharacterRange>* non_word = NULL; | |
| 3466 CharacterRange::Split(char_class->ranges(), | |
| 3467 CharacterRange::GetWordBounds(), | |
| 3468 &word, | |
| 3469 &non_word); | |
| 3470 if (non_word == NULL) { | |
| 3471 // This node contains no non-word characters so it must be | |
| 3472 // all word. | |
| 3473 this->info()->is_word = NodeInfo::TRUE; | |
| 3474 } else if (word == NULL) { | |
| 3475 // Vice versa. | |
| 3476 this->info()->is_word = NodeInfo::FALSE; | |
| 3477 } else { | |
| 3478 // If this character class contains both word and non-word | |
| 3479 // characters we need to split it into two. | |
| 3480 ChoiceNode* result = new ChoiceNode(2); | |
| 3481 // Welcome to the family, son! | |
| 3482 result->set_siblings(this->siblings()); | |
| 3483 *result->info() = *this->info(); | |
| 3484 result->info()->ResetCompilationState(); | |
| 3485 result->info()->AddAssumptions(info); | |
| 3486 RegExpNode* word_node | |
| 3487 = new TextNode(new RegExpCharacterClass(word, false), | |
| 3488 on_success()); | |
| 3489 word_node->info()->determine_word = true; | |
| 3490 word_node->info()->does_determine_word = true; | |
| 3491 word_node->info()->is_word = NodeInfo::TRUE; | |
| 3492 result->alternatives()->Add(GuardedAlternative(word_node)); | |
| 3493 RegExpNode* non_word_node | |
| 3494 = new TextNode(new RegExpCharacterClass(non_word, false), | |
| 3495 on_success()); | |
| 3496 non_word_node->info()->determine_word = true; | |
| 3497 non_word_node->info()->does_determine_word = true; | |
| 3498 non_word_node->info()->is_word = NodeInfo::FALSE; | |
| 3499 result->alternatives()->Add(GuardedAlternative(non_word_node)); | |
| 3500 return result; | |
| 3501 } | |
| 3502 } | |
| 3503 } | |
| 3504 TextNode* clone = this->Clone(); | |
| 3505 clone->info()->ResetCompilationState(); | |
| 3506 clone->info()->AddAssumptions(info); | |
| 3507 return clone; | |
| 3508 } | |
| 3509 | |
| 3510 | |
| 3511 void TextNode::ExpandAtomChildren(RegExpAtom* that) { | |
| 3512 NodeInfo new_info = *info(); | |
| 3513 uc16 last = that->data()[that->data().length() - 1]; | |
| 3514 if (info()->determine_word) { | |
| 3515 new_info.follows_word = IsRegExpWord(last) | |
| 3516 ? NodeInfo::TRUE : NodeInfo::FALSE; | |
| 3517 } else { | |
| 3518 new_info.follows_word = NodeInfo::UNKNOWN; | |
| 3519 } | |
| 3520 if (info()->determine_newline) { | |
| 3521 new_info.follows_newline = IsRegExpNewline(last) | |
| 3522 ? NodeInfo::TRUE : NodeInfo::FALSE; | |
| 3523 } else { | |
| 3524 new_info.follows_newline = NodeInfo::UNKNOWN; | |
| 3525 } | |
| 3526 if (info()->determine_start) { | |
| 3527 new_info.follows_start = NodeInfo::FALSE; | |
| 3528 } else { | |
| 3529 new_info.follows_start = NodeInfo::UNKNOWN; | |
| 3530 } | |
| 3531 set_on_success(on_success()->EnsureExpanded(&new_info)); | |
| 3532 } | |
| 3533 | |
| 3534 | |
| 3535 void TextNode::ExpandCharClassChildren(RegExpCharacterClass* that) { | |
| 3536 if (info()->does_determine_word) { | |
| 3537 // ASSERT(info()->is_word != NodeInfo::UNKNOWN); | |
| 3538 NodeInfo next_info = *on_success()->info(); | |
| 3539 next_info.follows_word = info()->is_word; | |
| 3540 set_on_success(on_success()->EnsureExpanded(&next_info)); | |
| 3541 } else { | |
| 3542 set_on_success(on_success()->EnsureExpanded(info())); | |
| 3543 } | |
| 3544 } | |
| 3545 | |
| 3546 | |
| 3547 void TextNode::ExpandChildren() { | |
| 3548 TextElement last = elements()->last(); | |
| 3549 switch (last.type) { | |
| 3550 case TextElement::ATOM: | |
| 3551 ExpandAtomChildren(last.data.u_atom); | |
| 3552 break; | |
| 3553 case TextElement::CHAR_CLASS: | |
| 3554 ExpandCharClassChildren(last.data.u_char_class); | |
| 3555 break; | |
| 3556 default: | |
| 3557 UNREACHABLE(); | |
| 3558 } | |
| 3559 } | |
| 3560 | |
| 3561 | |
| 3562 RegExpNode* ActionNode::ExpandLocal(NodeInfo* info) { | |
| 3563 ActionNode* clone = this->Clone(); | |
| 3564 clone->info()->ResetCompilationState(); | |
| 3565 clone->info()->AddAssumptions(info); | |
| 3566 return clone; | |
| 3567 } | |
| 3568 | |
| 3569 | |
| 3570 void ActionNode::ExpandChildren() { | |
| 3571 set_on_success(on_success()->EnsureExpanded(info())); | |
| 3572 } | |
| 3573 | |
| 3574 | |
| 3575 RegExpNode* BackReferenceNode::ExpandLocal(NodeInfo* info) { | |
| 3576 BackReferenceNode* clone = this->Clone(); | |
| 3577 clone->info()->ResetCompilationState(); | |
| 3578 clone->info()->AddAssumptions(info); | |
| 3579 return clone; | |
| 3580 } | |
| 3581 | |
| 3582 | |
| 3583 void BackReferenceNode::ExpandChildren() { | |
| 3584 set_on_success(on_success()->EnsureExpanded(info())); | |
| 3585 } | |
| 3586 | |
| 3587 | |
| 3588 RegExpNode* EndNode::ExpandLocal(NodeInfo* info) { | |
| 3589 EndNode* clone = this->Clone(); | |
| 3590 clone->info()->ResetCompilationState(); | |
| 3591 clone->info()->AddAssumptions(info); | |
| 3592 return clone; | |
| 3593 } | |
| 3594 | |
| 3595 | |
| 3596 void EndNode::ExpandChildren() { | |
| 3597 // nothing to do | |
| 3598 } | |
| 3599 | |
| 3600 | |
| 3601 // ------------------------------------------------------------------- | |
| 3602 // Dispatch table construction | 3383 // Dispatch table construction |
| 3603 | 3384 |
| 3604 | 3385 |
| 3605 void DispatchTableConstructor::VisitEnd(EndNode* that) { | 3386 void DispatchTableConstructor::VisitEnd(EndNode* that) { |
| 3606 AddRange(CharacterRange::Everything()); | 3387 AddRange(CharacterRange::Everything()); |
| 3607 } | 3388 } |
| 3608 | 3389 |
| 3609 | 3390 |
| 3610 void DispatchTableConstructor::BuildTable(ChoiceNode* node) { | 3391 void DispatchTableConstructor::BuildTable(ChoiceNode* node) { |
| 3611 node->set_being_calculated(true); | 3392 node->set_being_calculated(true); |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3701 } | 3482 } |
| 3702 } | 3483 } |
| 3703 | 3484 |
| 3704 | 3485 |
| 3705 void DispatchTableConstructor::VisitAction(ActionNode* that) { | 3486 void DispatchTableConstructor::VisitAction(ActionNode* that) { |
| 3706 RegExpNode* target = that->on_success(); | 3487 RegExpNode* target = that->on_success(); |
| 3707 target->Accept(this); | 3488 target->Accept(this); |
| 3708 } | 3489 } |
| 3709 | 3490 |
| 3710 | 3491 |
| 3711 #ifdef DEBUG | |
| 3712 | |
| 3713 | |
| 3714 class VisitNodeScope { | |
| 3715 public: | |
| 3716 explicit VisitNodeScope(RegExpNode* node) : node_(node) { | |
| 3717 ASSERT(!node->info()->visited); | |
| 3718 node->info()->visited = true; | |
| 3719 } | |
| 3720 ~VisitNodeScope() { | |
| 3721 node_->info()->visited = false; | |
| 3722 } | |
| 3723 private: | |
| 3724 RegExpNode* node_; | |
| 3725 }; | |
| 3726 | |
| 3727 | |
| 3728 class NodeValidator : public NodeVisitor { | |
| 3729 public: | |
| 3730 virtual void ValidateInfo(NodeInfo* info) = 0; | |
| 3731 #define DECLARE_VISIT(Type) \ | |
| 3732 virtual void Visit##Type(Type##Node* that); | |
| 3733 FOR_EACH_NODE_TYPE(DECLARE_VISIT) | |
| 3734 #undef DECLARE_VISIT | |
| 3735 }; | |
| 3736 | |
| 3737 | |
| 3738 class PostAnalysisNodeValidator : public NodeValidator { | |
| 3739 public: | |
| 3740 virtual void ValidateInfo(NodeInfo* info); | |
| 3741 }; | |
| 3742 | |
| 3743 | |
| 3744 class PostExpansionNodeValidator : public NodeValidator { | |
| 3745 public: | |
| 3746 virtual void ValidateInfo(NodeInfo* info); | |
| 3747 }; | |
| 3748 | |
| 3749 | |
| 3750 void PostAnalysisNodeValidator::ValidateInfo(NodeInfo* info) { | |
| 3751 ASSERT(info->been_analyzed); | |
| 3752 } | |
| 3753 | |
| 3754 | |
| 3755 void PostExpansionNodeValidator::ValidateInfo(NodeInfo* info) { | |
| 3756 ASSERT_EQ(info->determine_newline, info->does_determine_newline); | |
| 3757 ASSERT_EQ(info->determine_start, info->does_determine_start); | |
| 3758 ASSERT_EQ(info->determine_word, info->does_determine_word); | |
| 3759 ASSERT_EQ(info->follows_word_interest, | |
| 3760 (info->follows_word != NodeInfo::UNKNOWN)); | |
| 3761 if (false) { | |
| 3762 // These are still unimplemented. | |
| 3763 ASSERT_EQ(info->follows_start_interest, | |
| 3764 (info->follows_start != NodeInfo::UNKNOWN)); | |
| 3765 ASSERT_EQ(info->follows_newline_interest, | |
| 3766 (info->follows_newline != NodeInfo::UNKNOWN)); | |
| 3767 } | |
| 3768 } | |
| 3769 | |
| 3770 | |
| 3771 void NodeValidator::VisitAction(ActionNode* that) { | |
| 3772 if (that->info()->visited) return; | |
| 3773 VisitNodeScope scope(that); | |
| 3774 ValidateInfo(that->info()); | |
| 3775 that->on_success()->Accept(this); | |
| 3776 } | |
| 3777 | |
| 3778 | |
| 3779 void NodeValidator::VisitBackReference(BackReferenceNode* that) { | |
| 3780 if (that->info()->visited) return; | |
| 3781 VisitNodeScope scope(that); | |
| 3782 ValidateInfo(that->info()); | |
| 3783 that->on_success()->Accept(this); | |
| 3784 } | |
| 3785 | |
| 3786 | |
| 3787 void NodeValidator::VisitChoice(ChoiceNode* that) { | |
| 3788 if (that->info()->visited) return; | |
| 3789 VisitNodeScope scope(that); | |
| 3790 ValidateInfo(that->info()); | |
| 3791 ZoneList<GuardedAlternative>* alts = that->alternatives(); | |
| 3792 for (int i = 0; i < alts->length(); i++) | |
| 3793 alts->at(i).node()->Accept(this); | |
| 3794 } | |
| 3795 | |
| 3796 | |
| 3797 void NodeValidator::VisitEnd(EndNode* that) { | |
| 3798 if (that->info()->visited) return; | |
| 3799 VisitNodeScope scope(that); | |
| 3800 ValidateInfo(that->info()); | |
| 3801 } | |
| 3802 | |
| 3803 | |
| 3804 void NodeValidator::VisitText(TextNode* that) { | |
| 3805 if (that->info()->visited) return; | |
| 3806 VisitNodeScope scope(that); | |
| 3807 ValidateInfo(that->info()); | |
| 3808 that->on_success()->Accept(this); | |
| 3809 } | |
| 3810 | |
| 3811 | |
| 3812 #endif | |
| 3813 | |
| 3814 | |
| 3815 Handle<FixedArray> RegExpEngine::Compile(RegExpCompileData* data, | 3492 Handle<FixedArray> RegExpEngine::Compile(RegExpCompileData* data, |
| 3816 bool ignore_case, | 3493 bool ignore_case, |
| 3817 bool is_multiline, | 3494 bool is_multiline, |
| 3818 Handle<String> pattern, | 3495 Handle<String> pattern, |
| 3819 bool is_ascii) { | 3496 bool is_ascii) { |
| 3820 RegExpCompiler compiler(data->capture_count, ignore_case, is_ascii); | 3497 RegExpCompiler compiler(data->capture_count, ignore_case, is_ascii); |
| 3821 // Wrap the body of the regexp in capture #0. | 3498 // Wrap the body of the regexp in capture #0. |
| 3822 RegExpNode* captured_body = RegExpCapture::ToNode(data->tree, | 3499 RegExpNode* captured_body = RegExpCapture::ToNode(data->tree, |
| 3823 0, | 3500 0, |
| 3824 &compiler, | 3501 &compiler, |
| 3825 compiler.accept()); | 3502 compiler.accept()); |
| 3826 // Add a .*? at the beginning, outside the body capture. | 3503 // Add a .*? at the beginning, outside the body capture. |
| 3827 // Note: We could choose to not add this if the regexp is anchored at | 3504 // Note: We could choose to not add this if the regexp is anchored at |
| 3828 // the start of the input but I'm not sure how best to do that and | 3505 // the start of the input but I'm not sure how best to do that and |
| 3829 // since we don't even handle ^ yet I'm saving that optimization for | 3506 // since we don't even handle ^ yet I'm saving that optimization for |
| 3830 // later. | 3507 // later. |
| 3831 RegExpNode* node = RegExpQuantifier::ToNode(0, | 3508 RegExpNode* node = RegExpQuantifier::ToNode(0, |
| 3832 RegExpTree::kInfinity, | 3509 RegExpTree::kInfinity, |
| 3833 false, | 3510 false, |
| 3834 new RegExpCharacterClass('*'), | 3511 new RegExpCharacterClass('*'), |
| 3835 &compiler, | 3512 &compiler, |
| 3836 captured_body); | 3513 captured_body); |
| 3837 AssertionPropagation analysis(ignore_case); | 3514 data->node = node; |
| 3515 Analysis analysis(ignore_case); |
| 3838 analysis.EnsureAnalyzed(node); | 3516 analysis.EnsureAnalyzed(node); |
| 3839 | 3517 |
| 3840 NodeInfo info = *node->info(); | 3518 NodeInfo info = *node->info(); |
| 3841 data->has_lookbehind = info.HasLookbehind(); | |
| 3842 if (data->has_lookbehind) { | |
| 3843 // If this node needs information about the preceding text we let | |
| 3844 // it start with a character class that consumes a single character | |
| 3845 // and proceeds to wherever is appropriate. This means that if | |
| 3846 // has_lookbehind is set the code generator must start one character | |
| 3847 // before the start position. | |
| 3848 node = new TextNode(new RegExpCharacterClass('*'), node); | |
| 3849 analysis.EnsureAnalyzed(node); | |
| 3850 } | |
| 3851 | |
| 3852 #ifdef DEBUG | |
| 3853 PostAnalysisNodeValidator post_analysis_validator; | |
| 3854 node->Accept(&post_analysis_validator); | |
| 3855 #endif | |
| 3856 | |
| 3857 node = node->EnsureExpanded(&info); | |
| 3858 | |
| 3859 #ifdef DEBUG | |
| 3860 PostExpansionNodeValidator post_expansion_validator; | |
| 3861 node->Accept(&post_expansion_validator); | |
| 3862 #endif | |
| 3863 | |
| 3864 data->node = node; | |
| 3865 | 3519 |
| 3866 if (is_multiline && !FLAG_attempt_multiline_irregexp) { | 3520 if (is_multiline && !FLAG_attempt_multiline_irregexp) { |
| 3867 return Handle<FixedArray>::null(); | 3521 return Handle<FixedArray>::null(); |
| 3868 } | 3522 } |
| 3869 | 3523 |
| 3870 if (data->has_lookbehind) { | |
| 3871 return Handle<FixedArray>::null(); | |
| 3872 } | |
| 3873 | |
| 3874 if (FLAG_irregexp_native) { | 3524 if (FLAG_irregexp_native) { |
| 3875 #ifdef ARM | 3525 #ifdef ARM |
| 3876 // Unimplemented, fall-through to bytecode implementation. | 3526 // Unimplemented, fall-through to bytecode implementation. |
| 3877 #else // IA32 | 3527 #else // IA32 |
| 3878 RegExpMacroAssemblerIA32::Mode mode; | 3528 RegExpMacroAssemblerIA32::Mode mode; |
| 3879 if (is_ascii) { | 3529 if (is_ascii) { |
| 3880 mode = RegExpMacroAssemblerIA32::ASCII; | 3530 mode = RegExpMacroAssemblerIA32::ASCII; |
| 3881 } else { | 3531 } else { |
| 3882 mode = RegExpMacroAssemblerIA32::UC16; | 3532 mode = RegExpMacroAssemblerIA32::UC16; |
| 3883 } | 3533 } |
| 3884 RegExpMacroAssemblerIA32 macro_assembler(mode, | 3534 RegExpMacroAssemblerIA32 macro_assembler(mode, |
| 3885 (data->capture_count + 1) * 2); | 3535 (data->capture_count + 1) * 2); |
| 3886 return compiler.Assemble(¯o_assembler, | 3536 return compiler.Assemble(¯o_assembler, |
| 3887 node, | 3537 node, |
| 3888 data->capture_count, | 3538 data->capture_count, |
| 3889 pattern); | 3539 pattern); |
| 3890 #endif | 3540 #endif |
| 3891 } | 3541 } |
| 3892 EmbeddedVector<byte, 1024> codes; | 3542 EmbeddedVector<byte, 1024> codes; |
| 3893 RegExpMacroAssemblerIrregexp macro_assembler(codes); | 3543 RegExpMacroAssemblerIrregexp macro_assembler(codes); |
| 3894 return compiler.Assemble(¯o_assembler, | 3544 return compiler.Assemble(¯o_assembler, |
| 3895 node, | 3545 node, |
| 3896 data->capture_count, | 3546 data->capture_count, |
| 3897 pattern); | 3547 pattern); |
| 3898 } | 3548 } |
| 3899 | 3549 |
| 3900 | 3550 |
| 3901 }} // namespace v8::internal | 3551 }} // namespace v8::internal |
| OLD | NEW |