| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 932 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 943 | 943 |
| 944 TextElement TextElement::CharClass( | 944 TextElement TextElement::CharClass( |
| 945 RegExpCharacterClass* char_class) { | 945 RegExpCharacterClass* char_class) { |
| 946 TextElement result = TextElement(CHAR_CLASS); | 946 TextElement result = TextElement(CHAR_CLASS); |
| 947 result.data.u_char_class = char_class; | 947 result.data.u_char_class = char_class; |
| 948 return result; | 948 return result; |
| 949 } | 949 } |
| 950 | 950 |
| 951 | 951 |
| 952 int TextElement::length() { | 952 int TextElement::length() { |
| 953 if (type == ATOM) { | 953 if (text_type == ATOM) { |
| 954 return data.u_atom->length(); | 954 return data.u_atom->length(); |
| 955 } else { | 955 } else { |
| 956 ASSERT(type == CHAR_CLASS); | 956 ASSERT(text_type == CHAR_CLASS); |
| 957 return 1; | 957 return 1; |
| 958 } | 958 } |
| 959 } | 959 } |
| 960 | 960 |
| 961 | 961 |
| 962 DispatchTable* ChoiceNode::GetTable(bool ignore_case) { | 962 DispatchTable* ChoiceNode::GetTable(bool ignore_case) { |
| 963 if (table_ == NULL) { | 963 if (table_ == NULL) { |
| 964 table_ = new(zone()) DispatchTable(zone()); | 964 table_ = new(zone()) DispatchTable(zone()); |
| 965 DispatchTableConstructor cons(table_, ignore_case, zone()); | 965 DispatchTableConstructor cons(table_, ignore_case, zone()); |
| 966 cons.BuildTable(this); | 966 cons.BuildTable(this); |
| (...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1158 } | 1158 } |
| 1159 if (FLAG_trace_regexp_assembler) { | 1159 if (FLAG_trace_regexp_assembler) { |
| 1160 delete macro_assembler_; | 1160 delete macro_assembler_; |
| 1161 } | 1161 } |
| 1162 #endif | 1162 #endif |
| 1163 return RegExpEngine::CompilationResult(*code, next_register_); | 1163 return RegExpEngine::CompilationResult(*code, next_register_); |
| 1164 } | 1164 } |
| 1165 | 1165 |
| 1166 | 1166 |
| 1167 bool Trace::DeferredAction::Mentions(int that) { | 1167 bool Trace::DeferredAction::Mentions(int that) { |
| 1168 if (type() == ActionNode::CLEAR_CAPTURES) { | 1168 if (action_type() == ActionNode::CLEAR_CAPTURES) { |
| 1169 Interval range = static_cast<DeferredClearCaptures*>(this)->range(); | 1169 Interval range = static_cast<DeferredClearCaptures*>(this)->range(); |
| 1170 return range.Contains(that); | 1170 return range.Contains(that); |
| 1171 } else { | 1171 } else { |
| 1172 return reg() == that; | 1172 return reg() == that; |
| 1173 } | 1173 } |
| 1174 } | 1174 } |
| 1175 | 1175 |
| 1176 | 1176 |
| 1177 bool Trace::mentions_reg(int reg) { | 1177 bool Trace::mentions_reg(int reg) { |
| 1178 for (DeferredAction* action = actions_; | 1178 for (DeferredAction* action = actions_; |
| 1179 action != NULL; | 1179 action != NULL; |
| 1180 action = action->next()) { | 1180 action = action->next()) { |
| 1181 if (action->Mentions(reg)) | 1181 if (action->Mentions(reg)) |
| 1182 return true; | 1182 return true; |
| 1183 } | 1183 } |
| 1184 return false; | 1184 return false; |
| 1185 } | 1185 } |
| 1186 | 1186 |
| 1187 | 1187 |
| 1188 bool Trace::GetStoredPosition(int reg, int* cp_offset) { | 1188 bool Trace::GetStoredPosition(int reg, int* cp_offset) { |
| 1189 ASSERT_EQ(0, *cp_offset); | 1189 ASSERT_EQ(0, *cp_offset); |
| 1190 for (DeferredAction* action = actions_; | 1190 for (DeferredAction* action = actions_; |
| 1191 action != NULL; | 1191 action != NULL; |
| 1192 action = action->next()) { | 1192 action = action->next()) { |
| 1193 if (action->Mentions(reg)) { | 1193 if (action->Mentions(reg)) { |
| 1194 if (action->type() == ActionNode::STORE_POSITION) { | 1194 if (action->action_type() == ActionNode::STORE_POSITION) { |
| 1195 *cp_offset = static_cast<DeferredCapture*>(action)->cp_offset(); | 1195 *cp_offset = static_cast<DeferredCapture*>(action)->cp_offset(); |
| 1196 return true; | 1196 return true; |
| 1197 } else { | 1197 } else { |
| 1198 return false; | 1198 return false; |
| 1199 } | 1199 } |
| 1200 } | 1200 } |
| 1201 } | 1201 } |
| 1202 return false; | 1202 return false; |
| 1203 } | 1203 } |
| 1204 | 1204 |
| 1205 | 1205 |
| 1206 int Trace::FindAffectedRegisters(OutSet* affected_registers, | 1206 int Trace::FindAffectedRegisters(OutSet* affected_registers, |
| 1207 Zone* zone) { | 1207 Zone* zone) { |
| 1208 int max_register = RegExpCompiler::kNoRegister; | 1208 int max_register = RegExpCompiler::kNoRegister; |
| 1209 for (DeferredAction* action = actions_; | 1209 for (DeferredAction* action = actions_; |
| 1210 action != NULL; | 1210 action != NULL; |
| 1211 action = action->next()) { | 1211 action = action->next()) { |
| 1212 if (action->type() == ActionNode::CLEAR_CAPTURES) { | 1212 if (action->action_type() == ActionNode::CLEAR_CAPTURES) { |
| 1213 Interval range = static_cast<DeferredClearCaptures*>(action)->range(); | 1213 Interval range = static_cast<DeferredClearCaptures*>(action)->range(); |
| 1214 for (int i = range.from(); i <= range.to(); i++) | 1214 for (int i = range.from(); i <= range.to(); i++) |
| 1215 affected_registers->Set(i, zone); | 1215 affected_registers->Set(i, zone); |
| 1216 if (range.to() > max_register) max_register = range.to(); | 1216 if (range.to() > max_register) max_register = range.to(); |
| 1217 } else { | 1217 } else { |
| 1218 affected_registers->Set(action->reg(), zone); | 1218 affected_registers->Set(action->reg(), zone); |
| 1219 if (action->reg() > max_register) max_register = action->reg(); | 1219 if (action->reg() > max_register) max_register = action->reg(); |
| 1220 } | 1220 } |
| 1221 } | 1221 } |
| 1222 return max_register; | 1222 return max_register; |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1266 int value = 0; | 1266 int value = 0; |
| 1267 bool absolute = false; | 1267 bool absolute = false; |
| 1268 bool clear = false; | 1268 bool clear = false; |
| 1269 int store_position = -1; | 1269 int store_position = -1; |
| 1270 // This is a little tricky because we are scanning the actions in reverse | 1270 // This is a little tricky because we are scanning the actions in reverse |
| 1271 // historical order (newest first). | 1271 // historical order (newest first). |
| 1272 for (DeferredAction* action = actions_; | 1272 for (DeferredAction* action = actions_; |
| 1273 action != NULL; | 1273 action != NULL; |
| 1274 action = action->next()) { | 1274 action = action->next()) { |
| 1275 if (action->Mentions(reg)) { | 1275 if (action->Mentions(reg)) { |
| 1276 switch (action->type()) { | 1276 switch (action->action_type()) { |
| 1277 case ActionNode::SET_REGISTER: { | 1277 case ActionNode::SET_REGISTER: { |
| 1278 Trace::DeferredSetRegister* psr = | 1278 Trace::DeferredSetRegister* psr = |
| 1279 static_cast<Trace::DeferredSetRegister*>(action); | 1279 static_cast<Trace::DeferredSetRegister*>(action); |
| 1280 if (!absolute) { | 1280 if (!absolute) { |
| 1281 value += psr->value(); | 1281 value += psr->value(); |
| 1282 absolute = true; | 1282 absolute = true; |
| 1283 } | 1283 } |
| 1284 // SET_REGISTER is currently only used for newly introduced loop | 1284 // SET_REGISTER is currently only used for newly introduced loop |
| 1285 // counters. They can have a significant previous value if they | 1285 // counters. They can have a significant previous value if they |
| 1286 // occour in a loop. TODO(lrn): Propagate this information, so | 1286 // occour in a loop. TODO(lrn): Propagate this information, so |
| (...skipping 1010 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2297 // generic versions above can handle deep recursion properly. | 2297 // generic versions above can handle deep recursion properly. |
| 2298 trace->Flush(compiler, this); | 2298 trace->Flush(compiler, this); |
| 2299 return DONE; | 2299 return DONE; |
| 2300 } | 2300 } |
| 2301 | 2301 |
| 2302 | 2302 |
| 2303 int ActionNode::EatsAtLeast(int still_to_find, | 2303 int ActionNode::EatsAtLeast(int still_to_find, |
| 2304 int budget, | 2304 int budget, |
| 2305 bool not_at_start) { | 2305 bool not_at_start) { |
| 2306 if (budget <= 0) return 0; | 2306 if (budget <= 0) return 0; |
| 2307 if (type_ == POSITIVE_SUBMATCH_SUCCESS) return 0; // Rewinds input! | 2307 if (action_type_ == POSITIVE_SUBMATCH_SUCCESS) return 0; // Rewinds input! |
| 2308 return on_success()->EatsAtLeast(still_to_find, | 2308 return on_success()->EatsAtLeast(still_to_find, |
| 2309 budget - 1, | 2309 budget - 1, |
| 2310 not_at_start); | 2310 not_at_start); |
| 2311 } | 2311 } |
| 2312 | 2312 |
| 2313 | 2313 |
| 2314 void ActionNode::FillInBMInfo(int offset, | 2314 void ActionNode::FillInBMInfo(int offset, |
| 2315 int budget, | 2315 int budget, |
| 2316 BoyerMooreLookahead* bm, | 2316 BoyerMooreLookahead* bm, |
| 2317 bool not_at_start) { | 2317 bool not_at_start) { |
| 2318 if (type_ == BEGIN_SUBMATCH) { | 2318 if (action_type_ == BEGIN_SUBMATCH) { |
| 2319 bm->SetRest(offset); | 2319 bm->SetRest(offset); |
| 2320 } else if (type_ != POSITIVE_SUBMATCH_SUCCESS) { | 2320 } else if (action_type_ != POSITIVE_SUBMATCH_SUCCESS) { |
| 2321 on_success()->FillInBMInfo(offset, budget - 1, bm, not_at_start); | 2321 on_success()->FillInBMInfo(offset, budget - 1, bm, not_at_start); |
| 2322 } | 2322 } |
| 2323 SaveBMInfo(bm, not_at_start, offset); | 2323 SaveBMInfo(bm, not_at_start, offset); |
| 2324 } | 2324 } |
| 2325 | 2325 |
| 2326 | 2326 |
| 2327 int AssertionNode::EatsAtLeast(int still_to_find, | 2327 int AssertionNode::EatsAtLeast(int still_to_find, |
| 2328 int budget, | 2328 int budget, |
| 2329 bool not_at_start) { | 2329 bool not_at_start) { |
| 2330 if (budget <= 0) return 0; | 2330 if (budget <= 0) return 0; |
| 2331 // If we know we are not at the start and we are asked "how many characters | 2331 // If we know we are not at the start and we are asked "how many characters |
| 2332 // will you match if you succeed?" then we can answer anything since false | 2332 // will you match if you succeed?" then we can answer anything since false |
| 2333 // implies false. So lets just return the max answer (still_to_find) since | 2333 // implies false. So lets just return the max answer (still_to_find) since |
| 2334 // that won't prevent us from preloading a lot of characters for the other | 2334 // that won't prevent us from preloading a lot of characters for the other |
| 2335 // branches in the node graph. | 2335 // branches in the node graph. |
| 2336 if (type() == AT_START && not_at_start) return still_to_find; | 2336 if (assertion_type() == AT_START && not_at_start) return still_to_find; |
| 2337 return on_success()->EatsAtLeast(still_to_find, | 2337 return on_success()->EatsAtLeast(still_to_find, |
| 2338 budget - 1, | 2338 budget - 1, |
| 2339 not_at_start); | 2339 not_at_start); |
| 2340 } | 2340 } |
| 2341 | 2341 |
| 2342 | 2342 |
| 2343 void AssertionNode::FillInBMInfo(int offset, | 2343 void AssertionNode::FillInBMInfo(int offset, |
| 2344 int budget, | 2344 int budget, |
| 2345 BoyerMooreLookahead* bm, | 2345 BoyerMooreLookahead* bm, |
| 2346 bool not_at_start) { | 2346 bool not_at_start) { |
| 2347 // Match the behaviour of EatsAtLeast on this node. | 2347 // Match the behaviour of EatsAtLeast on this node. |
| 2348 if (type() == AT_START && not_at_start) return; | 2348 if (assertion_type() == AT_START && not_at_start) return; |
| 2349 on_success()->FillInBMInfo(offset, budget - 1, bm, not_at_start); | 2349 on_success()->FillInBMInfo(offset, budget - 1, bm, not_at_start); |
| 2350 SaveBMInfo(bm, not_at_start, offset); | 2350 SaveBMInfo(bm, not_at_start, offset); |
| 2351 } | 2351 } |
| 2352 | 2352 |
| 2353 | 2353 |
| 2354 int BackReferenceNode::EatsAtLeast(int still_to_find, | 2354 int BackReferenceNode::EatsAtLeast(int still_to_find, |
| 2355 int budget, | 2355 int budget, |
| 2356 bool not_at_start) { | 2356 bool not_at_start) { |
| 2357 if (budget <= 0) return 0; | 2357 if (budget <= 0) return 0; |
| 2358 return on_success()->EatsAtLeast(still_to_find, | 2358 return on_success()->EatsAtLeast(still_to_find, |
| (...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2555 ASSERT(characters_filled_in < details->characters()); | 2555 ASSERT(characters_filled_in < details->characters()); |
| 2556 int characters = details->characters(); | 2556 int characters = details->characters(); |
| 2557 int char_mask; | 2557 int char_mask; |
| 2558 if (compiler->ascii()) { | 2558 if (compiler->ascii()) { |
| 2559 char_mask = String::kMaxOneByteCharCode; | 2559 char_mask = String::kMaxOneByteCharCode; |
| 2560 } else { | 2560 } else { |
| 2561 char_mask = String::kMaxUtf16CodeUnit; | 2561 char_mask = String::kMaxUtf16CodeUnit; |
| 2562 } | 2562 } |
| 2563 for (int k = 0; k < elms_->length(); k++) { | 2563 for (int k = 0; k < elms_->length(); k++) { |
| 2564 TextElement elm = elms_->at(k); | 2564 TextElement elm = elms_->at(k); |
| 2565 if (elm.type == TextElement::ATOM) { | 2565 if (elm.text_type == TextElement::ATOM) { |
| 2566 Vector<const uc16> quarks = elm.data.u_atom->data(); | 2566 Vector<const uc16> quarks = elm.data.u_atom->data(); |
| 2567 for (int i = 0; i < characters && i < quarks.length(); i++) { | 2567 for (int i = 0; i < characters && i < quarks.length(); i++) { |
| 2568 QuickCheckDetails::Position* pos = | 2568 QuickCheckDetails::Position* pos = |
| 2569 details->positions(characters_filled_in); | 2569 details->positions(characters_filled_in); |
| 2570 uc16 c = quarks[i]; | 2570 uc16 c = quarks[i]; |
| 2571 if (c > char_mask) { | 2571 if (c > char_mask) { |
| 2572 // If we expect a non-ASCII character from an ASCII string, | 2572 // If we expect a non-ASCII character from an ASCII string, |
| 2573 // there is no way we can match. Not even case independent | 2573 // there is no way we can match. Not even case independent |
| 2574 // matching can turn an ASCII character into non-ASCII or | 2574 // matching can turn an ASCII character into non-ASCII or |
| 2575 // vice versa. | 2575 // vice versa. |
| (...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2808 | 2808 |
| 2809 | 2809 |
| 2810 RegExpNode* TextNode::FilterASCII(int depth, bool ignore_case) { | 2810 RegExpNode* TextNode::FilterASCII(int depth, bool ignore_case) { |
| 2811 if (info()->replacement_calculated) return replacement(); | 2811 if (info()->replacement_calculated) return replacement(); |
| 2812 if (depth < 0) return this; | 2812 if (depth < 0) return this; |
| 2813 ASSERT(!info()->visited); | 2813 ASSERT(!info()->visited); |
| 2814 VisitMarker marker(info()); | 2814 VisitMarker marker(info()); |
| 2815 int element_count = elms_->length(); | 2815 int element_count = elms_->length(); |
| 2816 for (int i = 0; i < element_count; i++) { | 2816 for (int i = 0; i < element_count; i++) { |
| 2817 TextElement elm = elms_->at(i); | 2817 TextElement elm = elms_->at(i); |
| 2818 if (elm.type == TextElement::ATOM) { | 2818 if (elm.text_type == TextElement::ATOM) { |
| 2819 Vector<const uc16> quarks = elm.data.u_atom->data(); | 2819 Vector<const uc16> quarks = elm.data.u_atom->data(); |
| 2820 for (int j = 0; j < quarks.length(); j++) { | 2820 for (int j = 0; j < quarks.length(); j++) { |
| 2821 uint16_t c = quarks[j]; | 2821 uint16_t c = quarks[j]; |
| 2822 if (c <= String::kMaxOneByteCharCode) continue; | 2822 if (c <= String::kMaxOneByteCharCode) continue; |
| 2823 if (!ignore_case) return set_replacement(NULL); | 2823 if (!ignore_case) return set_replacement(NULL); |
| 2824 // Here, we need to check for characters whose upper and lower cases | 2824 // Here, we need to check for characters whose upper and lower cases |
| 2825 // are outside the Latin-1 range. | 2825 // are outside the Latin-1 range. |
| 2826 uint16_t converted = unibrow::Latin1::ConvertNonLatin1ToLatin1(c); | 2826 uint16_t converted = unibrow::Latin1::ConvertNonLatin1ToLatin1(c); |
| 2827 // Character is outside Latin-1 completely | 2827 // Character is outside Latin-1 completely |
| 2828 if (converted == 0) return set_replacement(NULL); | 2828 if (converted == 0) return set_replacement(NULL); |
| 2829 // Convert quark to Latin-1 in place. | 2829 // Convert quark to Latin-1 in place. |
| 2830 uint16_t* copy = const_cast<uint16_t*>(quarks.start()); | 2830 uint16_t* copy = const_cast<uint16_t*>(quarks.start()); |
| 2831 copy[j] = converted; | 2831 copy[j] = converted; |
| 2832 } | 2832 } |
| 2833 } else { | 2833 } else { |
| 2834 ASSERT(elm.type == TextElement::CHAR_CLASS); | 2834 ASSERT(elm.text_type == TextElement::CHAR_CLASS); |
| 2835 RegExpCharacterClass* cc = elm.data.u_char_class; | 2835 RegExpCharacterClass* cc = elm.data.u_char_class; |
| 2836 ZoneList<CharacterRange>* ranges = cc->ranges(zone()); | 2836 ZoneList<CharacterRange>* ranges = cc->ranges(zone()); |
| 2837 if (!CharacterRange::IsCanonical(ranges)) { | 2837 if (!CharacterRange::IsCanonical(ranges)) { |
| 2838 CharacterRange::Canonicalize(ranges); | 2838 CharacterRange::Canonicalize(ranges); |
| 2839 } | 2839 } |
| 2840 // Now they are in order so we only need to look at the first. | 2840 // Now they are in order so we only need to look at the first. |
| 2841 int range_count = ranges->length(); | 2841 int range_count = ranges->length(); |
| 2842 if (cc->is_negated()) { | 2842 if (cc->is_negated()) { |
| 2843 if (range_count != 0 && | 2843 if (range_count != 0 && |
| 2844 ranges->at(0).from() == 0 && | 2844 ranges->at(0).from() == 0 && |
| (...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3079 BoyerMooreLookahead* bm = | 3079 BoyerMooreLookahead* bm = |
| 3080 new(zone()) BoyerMooreLookahead(eats_at_least, compiler, zone()); | 3080 new(zone()) BoyerMooreLookahead(eats_at_least, compiler, zone()); |
| 3081 FillInBMInfo(0, kRecursionBudget, bm, not_at_start); | 3081 FillInBMInfo(0, kRecursionBudget, bm, not_at_start); |
| 3082 if (bm->at(0)->is_non_word()) next_is_word_character = Trace::FALSE; | 3082 if (bm->at(0)->is_non_word()) next_is_word_character = Trace::FALSE; |
| 3083 if (bm->at(0)->is_word()) next_is_word_character = Trace::TRUE; | 3083 if (bm->at(0)->is_word()) next_is_word_character = Trace::TRUE; |
| 3084 } | 3084 } |
| 3085 } else { | 3085 } else { |
| 3086 if (lookahead->at(0)->is_non_word()) next_is_word_character = Trace::FALSE; | 3086 if (lookahead->at(0)->is_non_word()) next_is_word_character = Trace::FALSE; |
| 3087 if (lookahead->at(0)->is_word()) next_is_word_character = Trace::TRUE; | 3087 if (lookahead->at(0)->is_word()) next_is_word_character = Trace::TRUE; |
| 3088 } | 3088 } |
| 3089 bool at_boundary = (type_ == AssertionNode::AT_BOUNDARY); | 3089 bool at_boundary = (assertion_type_ == AssertionNode::AT_BOUNDARY); |
| 3090 if (next_is_word_character == Trace::UNKNOWN) { | 3090 if (next_is_word_character == Trace::UNKNOWN) { |
| 3091 Label before_non_word; | 3091 Label before_non_word; |
| 3092 Label before_word; | 3092 Label before_word; |
| 3093 if (trace->characters_preloaded() != 1) { | 3093 if (trace->characters_preloaded() != 1) { |
| 3094 assembler->LoadCurrentCharacter(trace->cp_offset(), &before_non_word); | 3094 assembler->LoadCurrentCharacter(trace->cp_offset(), &before_non_word); |
| 3095 } | 3095 } |
| 3096 // Fall through on non-word. | 3096 // Fall through on non-word. |
| 3097 EmitWordCheck(assembler, &before_word, &before_non_word, false); | 3097 EmitWordCheck(assembler, &before_word, &before_non_word, false); |
| 3098 // Next character is not a word character. | 3098 // Next character is not a word character. |
| 3099 assembler->Bind(&before_non_word); | 3099 assembler->Bind(&before_non_word); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3142 | 3142 |
| 3143 assembler->Bind(&fall_through); | 3143 assembler->Bind(&fall_through); |
| 3144 on_success()->Emit(compiler, &new_trace); | 3144 on_success()->Emit(compiler, &new_trace); |
| 3145 } | 3145 } |
| 3146 | 3146 |
| 3147 | 3147 |
| 3148 void AssertionNode::GetQuickCheckDetails(QuickCheckDetails* details, | 3148 void AssertionNode::GetQuickCheckDetails(QuickCheckDetails* details, |
| 3149 RegExpCompiler* compiler, | 3149 RegExpCompiler* compiler, |
| 3150 int filled_in, | 3150 int filled_in, |
| 3151 bool not_at_start) { | 3151 bool not_at_start) { |
| 3152 if (type_ == AT_START && not_at_start) { | 3152 if (assertion_type_ == AT_START && not_at_start) { |
| 3153 details->set_cannot_match(); | 3153 details->set_cannot_match(); |
| 3154 return; | 3154 return; |
| 3155 } | 3155 } |
| 3156 return on_success()->GetQuickCheckDetails(details, | 3156 return on_success()->GetQuickCheckDetails(details, |
| 3157 compiler, | 3157 compiler, |
| 3158 filled_in, | 3158 filled_in, |
| 3159 not_at_start); | 3159 not_at_start); |
| 3160 } | 3160 } |
| 3161 | 3161 |
| 3162 | 3162 |
| 3163 void AssertionNode::Emit(RegExpCompiler* compiler, Trace* trace) { | 3163 void AssertionNode::Emit(RegExpCompiler* compiler, Trace* trace) { |
| 3164 RegExpMacroAssembler* assembler = compiler->macro_assembler(); | 3164 RegExpMacroAssembler* assembler = compiler->macro_assembler(); |
| 3165 switch (type_) { | 3165 switch (assertion_type_) { |
| 3166 case AT_END: { | 3166 case AT_END: { |
| 3167 Label ok; | 3167 Label ok; |
| 3168 assembler->CheckPosition(trace->cp_offset(), &ok); | 3168 assembler->CheckPosition(trace->cp_offset(), &ok); |
| 3169 assembler->GoTo(trace->backtrack()); | 3169 assembler->GoTo(trace->backtrack()); |
| 3170 assembler->Bind(&ok); | 3170 assembler->Bind(&ok); |
| 3171 break; | 3171 break; |
| 3172 } | 3172 } |
| 3173 case AT_START: { | 3173 case AT_START: { |
| 3174 if (trace->at_start() == Trace::FALSE) { | 3174 if (trace->at_start() == Trace::FALSE) { |
| 3175 assembler->GoTo(trace->backtrack()); | 3175 assembler->GoTo(trace->backtrack()); |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3248 int* checked_up_to) { | 3248 int* checked_up_to) { |
| 3249 Isolate* isolate = Isolate::Current(); | 3249 Isolate* isolate = Isolate::Current(); |
| 3250 RegExpMacroAssembler* assembler = compiler->macro_assembler(); | 3250 RegExpMacroAssembler* assembler = compiler->macro_assembler(); |
| 3251 bool ascii = compiler->ascii(); | 3251 bool ascii = compiler->ascii(); |
| 3252 Label* backtrack = trace->backtrack(); | 3252 Label* backtrack = trace->backtrack(); |
| 3253 QuickCheckDetails* quick_check = trace->quick_check_performed(); | 3253 QuickCheckDetails* quick_check = trace->quick_check_performed(); |
| 3254 int element_count = elms_->length(); | 3254 int element_count = elms_->length(); |
| 3255 for (int i = preloaded ? 0 : element_count - 1; i >= 0; i--) { | 3255 for (int i = preloaded ? 0 : element_count - 1; i >= 0; i--) { |
| 3256 TextElement elm = elms_->at(i); | 3256 TextElement elm = elms_->at(i); |
| 3257 int cp_offset = trace->cp_offset() + elm.cp_offset; | 3257 int cp_offset = trace->cp_offset() + elm.cp_offset; |
| 3258 if (elm.type == TextElement::ATOM) { | 3258 if (elm.text_type == TextElement::ATOM) { |
| 3259 Vector<const uc16> quarks = elm.data.u_atom->data(); | 3259 Vector<const uc16> quarks = elm.data.u_atom->data(); |
| 3260 for (int j = preloaded ? 0 : quarks.length() - 1; j >= 0; j--) { | 3260 for (int j = preloaded ? 0 : quarks.length() - 1; j >= 0; j--) { |
| 3261 if (first_element_checked && i == 0 && j == 0) continue; | 3261 if (first_element_checked && i == 0 && j == 0) continue; |
| 3262 if (DeterminedAlready(quick_check, elm.cp_offset + j)) continue; | 3262 if (DeterminedAlready(quick_check, elm.cp_offset + j)) continue; |
| 3263 EmitCharacterFunction* emit_function = NULL; | 3263 EmitCharacterFunction* emit_function = NULL; |
| 3264 switch (pass) { | 3264 switch (pass) { |
| 3265 case NON_ASCII_MATCH: | 3265 case NON_ASCII_MATCH: |
| 3266 ASSERT(ascii); | 3266 ASSERT(ascii); |
| 3267 if (quarks[j] > String::kMaxOneByteCharCode) { | 3267 if (quarks[j] > String::kMaxOneByteCharCode) { |
| 3268 assembler->GoTo(backtrack); | 3268 assembler->GoTo(backtrack); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 3286 compiler, | 3286 compiler, |
| 3287 quarks[j], | 3287 quarks[j], |
| 3288 backtrack, | 3288 backtrack, |
| 3289 cp_offset + j, | 3289 cp_offset + j, |
| 3290 *checked_up_to < cp_offset + j, | 3290 *checked_up_to < cp_offset + j, |
| 3291 preloaded); | 3291 preloaded); |
| 3292 if (bound_checked) UpdateBoundsCheck(cp_offset + j, checked_up_to); | 3292 if (bound_checked) UpdateBoundsCheck(cp_offset + j, checked_up_to); |
| 3293 } | 3293 } |
| 3294 } | 3294 } |
| 3295 } else { | 3295 } else { |
| 3296 ASSERT_EQ(elm.type, TextElement::CHAR_CLASS); | 3296 ASSERT_EQ(elm.text_type, TextElement::CHAR_CLASS); |
| 3297 if (pass == CHARACTER_CLASS_MATCH) { | 3297 if (pass == CHARACTER_CLASS_MATCH) { |
| 3298 if (first_element_checked && i == 0) continue; | 3298 if (first_element_checked && i == 0) continue; |
| 3299 if (DeterminedAlready(quick_check, elm.cp_offset)) continue; | 3299 if (DeterminedAlready(quick_check, elm.cp_offset)) continue; |
| 3300 RegExpCharacterClass* cc = elm.data.u_char_class; | 3300 RegExpCharacterClass* cc = elm.data.u_char_class; |
| 3301 EmitCharClass(assembler, | 3301 EmitCharClass(assembler, |
| 3302 cc, | 3302 cc, |
| 3303 ascii, | 3303 ascii, |
| 3304 backtrack, | 3304 backtrack, |
| 3305 cp_offset, | 3305 cp_offset, |
| 3306 *checked_up_to < cp_offset, | 3306 *checked_up_to < cp_offset, |
| 3307 preloaded, | 3307 preloaded, |
| 3308 zone()); | 3308 zone()); |
| 3309 UpdateBoundsCheck(cp_offset, checked_up_to); | 3309 UpdateBoundsCheck(cp_offset, checked_up_to); |
| 3310 } | 3310 } |
| 3311 } | 3311 } |
| 3312 } | 3312 } |
| 3313 } | 3313 } |
| 3314 | 3314 |
| 3315 | 3315 |
| 3316 int TextNode::Length() { | 3316 int TextNode::Length() { |
| 3317 TextElement elm = elms_->last(); | 3317 TextElement elm = elms_->last(); |
| 3318 ASSERT(elm.cp_offset >= 0); | 3318 ASSERT(elm.cp_offset >= 0); |
| 3319 if (elm.type == TextElement::ATOM) { | 3319 if (elm.text_type == TextElement::ATOM) { |
| 3320 return elm.cp_offset + elm.data.u_atom->data().length(); | 3320 return elm.cp_offset + elm.data.u_atom->data().length(); |
| 3321 } else { | 3321 } else { |
| 3322 return elm.cp_offset + 1; | 3322 return elm.cp_offset + 1; |
| 3323 } | 3323 } |
| 3324 } | 3324 } |
| 3325 | 3325 |
| 3326 | 3326 |
| 3327 bool TextNode::SkipPass(int int_pass, bool ignore_case) { | 3327 bool TextNode::SkipPass(int int_pass, bool ignore_case) { |
| 3328 TextEmitPassType pass = static_cast<TextEmitPassType>(int_pass); | 3328 TextEmitPassType pass = static_cast<TextEmitPassType>(int_pass); |
| 3329 if (ignore_case) { | 3329 if (ignore_case) { |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3415 cp_offset_ = 0; | 3415 cp_offset_ = 0; |
| 3416 } | 3416 } |
| 3417 bound_checked_up_to_ = Max(0, bound_checked_up_to_ - by); | 3417 bound_checked_up_to_ = Max(0, bound_checked_up_to_ - by); |
| 3418 } | 3418 } |
| 3419 | 3419 |
| 3420 | 3420 |
| 3421 void TextNode::MakeCaseIndependent(bool is_ascii) { | 3421 void TextNode::MakeCaseIndependent(bool is_ascii) { |
| 3422 int element_count = elms_->length(); | 3422 int element_count = elms_->length(); |
| 3423 for (int i = 0; i < element_count; i++) { | 3423 for (int i = 0; i < element_count; i++) { |
| 3424 TextElement elm = elms_->at(i); | 3424 TextElement elm = elms_->at(i); |
| 3425 if (elm.type == TextElement::CHAR_CLASS) { | 3425 if (elm.text_type == TextElement::CHAR_CLASS) { |
| 3426 RegExpCharacterClass* cc = elm.data.u_char_class; | 3426 RegExpCharacterClass* cc = elm.data.u_char_class; |
| 3427 // None of the standard character classes is different in the case | 3427 // None of the standard character classes is different in the case |
| 3428 // independent case and it slows us down if we don't know that. | 3428 // independent case and it slows us down if we don't know that. |
| 3429 if (cc->is_standard(zone())) continue; | 3429 if (cc->is_standard(zone())) continue; |
| 3430 ZoneList<CharacterRange>* ranges = cc->ranges(zone()); | 3430 ZoneList<CharacterRange>* ranges = cc->ranges(zone()); |
| 3431 int range_count = ranges->length(); | 3431 int range_count = ranges->length(); |
| 3432 for (int j = 0; j < range_count; j++) { | 3432 for (int j = 0; j < range_count; j++) { |
| 3433 ranges->at(j).AddCaseEquivalents(ranges, is_ascii, zone()); | 3433 ranges->at(j).AddCaseEquivalents(ranges, is_ascii, zone()); |
| 3434 } | 3434 } |
| 3435 } | 3435 } |
| 3436 } | 3436 } |
| 3437 } | 3437 } |
| 3438 | 3438 |
| 3439 | 3439 |
| 3440 int TextNode::GreedyLoopTextLength() { | 3440 int TextNode::GreedyLoopTextLength() { |
| 3441 TextElement elm = elms_->at(elms_->length() - 1); | 3441 TextElement elm = elms_->at(elms_->length() - 1); |
| 3442 if (elm.type == TextElement::CHAR_CLASS) { | 3442 if (elm.text_type == TextElement::CHAR_CLASS) { |
| 3443 return elm.cp_offset + 1; | 3443 return elm.cp_offset + 1; |
| 3444 } else { | 3444 } else { |
| 3445 return elm.cp_offset + elm.data.u_atom->data().length(); | 3445 return elm.cp_offset + elm.data.u_atom->data().length(); |
| 3446 } | 3446 } |
| 3447 } | 3447 } |
| 3448 | 3448 |
| 3449 | 3449 |
| 3450 RegExpNode* TextNode::GetSuccessorOfOmnivorousTextNode( | 3450 RegExpNode* TextNode::GetSuccessorOfOmnivorousTextNode( |
| 3451 RegExpCompiler* compiler) { | 3451 RegExpCompiler* compiler) { |
| 3452 if (elms_->length() != 1) return NULL; | 3452 if (elms_->length() != 1) return NULL; |
| 3453 TextElement elm = elms_->at(0); | 3453 TextElement elm = elms_->at(0); |
| 3454 if (elm.type != TextElement::CHAR_CLASS) return NULL; | 3454 if (elm.text_type != TextElement::CHAR_CLASS) return NULL; |
| 3455 RegExpCharacterClass* node = elm.data.u_char_class; | 3455 RegExpCharacterClass* node = elm.data.u_char_class; |
| 3456 ZoneList<CharacterRange>* ranges = node->ranges(zone()); | 3456 ZoneList<CharacterRange>* ranges = node->ranges(zone()); |
| 3457 if (!CharacterRange::IsCanonical(ranges)) { | 3457 if (!CharacterRange::IsCanonical(ranges)) { |
| 3458 CharacterRange::Canonicalize(ranges); | 3458 CharacterRange::Canonicalize(ranges); |
| 3459 } | 3459 } |
| 3460 if (node->is_negated()) { | 3460 if (node->is_negated()) { |
| 3461 return ranges->length() == 0 ? on_success() : NULL; | 3461 return ranges->length() == 0 ? on_success() : NULL; |
| 3462 } | 3462 } |
| 3463 if (ranges->length() != 1) return NULL; | 3463 if (ranges->length() != 1) return NULL; |
| 3464 uint32_t max_char; | 3464 uint32_t max_char; |
| (...skipping 724 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4189 | 4189 |
| 4190 | 4190 |
| 4191 void ActionNode::Emit(RegExpCompiler* compiler, Trace* trace) { | 4191 void ActionNode::Emit(RegExpCompiler* compiler, Trace* trace) { |
| 4192 RegExpMacroAssembler* assembler = compiler->macro_assembler(); | 4192 RegExpMacroAssembler* assembler = compiler->macro_assembler(); |
| 4193 LimitResult limit_result = LimitVersions(compiler, trace); | 4193 LimitResult limit_result = LimitVersions(compiler, trace); |
| 4194 if (limit_result == DONE) return; | 4194 if (limit_result == DONE) return; |
| 4195 ASSERT(limit_result == CONTINUE); | 4195 ASSERT(limit_result == CONTINUE); |
| 4196 | 4196 |
| 4197 RecursionCheck rc(compiler); | 4197 RecursionCheck rc(compiler); |
| 4198 | 4198 |
| 4199 switch (type_) { | 4199 switch (action_type_) { |
| 4200 case STORE_POSITION: { | 4200 case STORE_POSITION: { |
| 4201 Trace::DeferredCapture | 4201 Trace::DeferredCapture |
| 4202 new_capture(data_.u_position_register.reg, | 4202 new_capture(data_.u_position_register.reg, |
| 4203 data_.u_position_register.is_capture, | 4203 data_.u_position_register.is_capture, |
| 4204 trace); | 4204 trace); |
| 4205 Trace new_trace = *trace; | 4205 Trace new_trace = *trace; |
| 4206 new_trace.add_action(&new_capture); | 4206 new_trace.add_action(&new_capture); |
| 4207 on_success()->Emit(compiler, &new_trace); | 4207 on_success()->Emit(compiler, &new_trace); |
| 4208 break; | 4208 break; |
| 4209 } | 4209 } |
| (...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4519 } | 4519 } |
| 4520 } | 4520 } |
| 4521 | 4521 |
| 4522 | 4522 |
| 4523 void DotPrinter::VisitText(TextNode* that) { | 4523 void DotPrinter::VisitText(TextNode* that) { |
| 4524 Zone* zone = that->zone(); | 4524 Zone* zone = that->zone(); |
| 4525 stream()->Add(" n%p [label=\"", that); | 4525 stream()->Add(" n%p [label=\"", that); |
| 4526 for (int i = 0; i < that->elements()->length(); i++) { | 4526 for (int i = 0; i < that->elements()->length(); i++) { |
| 4527 if (i > 0) stream()->Add(" "); | 4527 if (i > 0) stream()->Add(" "); |
| 4528 TextElement elm = that->elements()->at(i); | 4528 TextElement elm = that->elements()->at(i); |
| 4529 switch (elm.type) { | 4529 switch (elm.text_type) { |
| 4530 case TextElement::ATOM: { | 4530 case TextElement::ATOM: { |
| 4531 stream()->Add("'%w'", elm.data.u_atom->data()); | 4531 stream()->Add("'%w'", elm.data.u_atom->data()); |
| 4532 break; | 4532 break; |
| 4533 } | 4533 } |
| 4534 case TextElement::CHAR_CLASS: { | 4534 case TextElement::CHAR_CLASS: { |
| 4535 RegExpCharacterClass* node = elm.data.u_char_class; | 4535 RegExpCharacterClass* node = elm.data.u_char_class; |
| 4536 stream()->Add("["); | 4536 stream()->Add("["); |
| 4537 if (node->is_negated()) | 4537 if (node->is_negated()) |
| 4538 stream()->Add("^"); | 4538 stream()->Add("^"); |
| 4539 for (int j = 0; j < node->ranges(zone)->length(); j++) { | 4539 for (int j = 0; j < node->ranges(zone)->length(); j++) { |
| (...skipping 26 matching lines...) Expand all Loading... |
| 4566 | 4566 |
| 4567 | 4567 |
| 4568 void DotPrinter::VisitEnd(EndNode* that) { | 4568 void DotPrinter::VisitEnd(EndNode* that) { |
| 4569 stream()->Add(" n%p [style=bold, shape=point];\n", that); | 4569 stream()->Add(" n%p [style=bold, shape=point];\n", that); |
| 4570 PrintAttributes(that); | 4570 PrintAttributes(that); |
| 4571 } | 4571 } |
| 4572 | 4572 |
| 4573 | 4573 |
| 4574 void DotPrinter::VisitAssertion(AssertionNode* that) { | 4574 void DotPrinter::VisitAssertion(AssertionNode* that) { |
| 4575 stream()->Add(" n%p [", that); | 4575 stream()->Add(" n%p [", that); |
| 4576 switch (that->type()) { | 4576 switch (that->assertion_type()) { |
| 4577 case AssertionNode::AT_END: | 4577 case AssertionNode::AT_END: |
| 4578 stream()->Add("label=\"$\", shape=septagon"); | 4578 stream()->Add("label=\"$\", shape=septagon"); |
| 4579 break; | 4579 break; |
| 4580 case AssertionNode::AT_START: | 4580 case AssertionNode::AT_START: |
| 4581 stream()->Add("label=\"^\", shape=septagon"); | 4581 stream()->Add("label=\"^\", shape=septagon"); |
| 4582 break; | 4582 break; |
| 4583 case AssertionNode::AT_BOUNDARY: | 4583 case AssertionNode::AT_BOUNDARY: |
| 4584 stream()->Add("label=\"\\b\", shape=septagon"); | 4584 stream()->Add("label=\"\\b\", shape=septagon"); |
| 4585 break; | 4585 break; |
| 4586 case AssertionNode::AT_NON_BOUNDARY: | 4586 case AssertionNode::AT_NON_BOUNDARY: |
| 4587 stream()->Add("label=\"\\B\", shape=septagon"); | 4587 stream()->Add("label=\"\\B\", shape=septagon"); |
| 4588 break; | 4588 break; |
| 4589 case AssertionNode::AFTER_NEWLINE: | 4589 case AssertionNode::AFTER_NEWLINE: |
| 4590 stream()->Add("label=\"(?<=\\n)\", shape=septagon"); | 4590 stream()->Add("label=\"(?<=\\n)\", shape=septagon"); |
| 4591 break; | 4591 break; |
| 4592 } | 4592 } |
| 4593 stream()->Add("];\n"); | 4593 stream()->Add("];\n"); |
| 4594 PrintAttributes(that); | 4594 PrintAttributes(that); |
| 4595 RegExpNode* successor = that->on_success(); | 4595 RegExpNode* successor = that->on_success(); |
| 4596 stream()->Add(" n%p -> n%p;\n", that, successor); | 4596 stream()->Add(" n%p -> n%p;\n", that, successor); |
| 4597 Visit(successor); | 4597 Visit(successor); |
| 4598 } | 4598 } |
| 4599 | 4599 |
| 4600 | 4600 |
| 4601 void DotPrinter::VisitAction(ActionNode* that) { | 4601 void DotPrinter::VisitAction(ActionNode* that) { |
| 4602 stream()->Add(" n%p [", that); | 4602 stream()->Add(" n%p [", that); |
| 4603 switch (that->type_) { | 4603 switch (that->action_type_) { |
| 4604 case ActionNode::SET_REGISTER: | 4604 case ActionNode::SET_REGISTER: |
| 4605 stream()->Add("label=\"$%i:=%i\", shape=octagon", | 4605 stream()->Add("label=\"$%i:=%i\", shape=octagon", |
| 4606 that->data_.u_store_register.reg, | 4606 that->data_.u_store_register.reg, |
| 4607 that->data_.u_store_register.value); | 4607 that->data_.u_store_register.value); |
| 4608 break; | 4608 break; |
| 4609 case ActionNode::INCREMENT_REGISTER: | 4609 case ActionNode::INCREMENT_REGISTER: |
| 4610 stream()->Add("label=\"$%i++\", shape=octagon", | 4610 stream()->Add("label=\"$%i++\", shape=octagon", |
| 4611 that->data_.u_increment_register.reg); | 4611 that->data_.u_increment_register.reg); |
| 4612 break; | 4612 break; |
| 4613 case ActionNode::STORE_POSITION: | 4613 case ActionNode::STORE_POSITION: |
| (...skipping 392 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5006 return center; | 5006 return center; |
| 5007 } | 5007 } |
| 5008 } | 5008 } |
| 5009 | 5009 |
| 5010 | 5010 |
| 5011 RegExpNode* RegExpAssertion::ToNode(RegExpCompiler* compiler, | 5011 RegExpNode* RegExpAssertion::ToNode(RegExpCompiler* compiler, |
| 5012 RegExpNode* on_success) { | 5012 RegExpNode* on_success) { |
| 5013 NodeInfo info; | 5013 NodeInfo info; |
| 5014 Zone* zone = compiler->zone(); | 5014 Zone* zone = compiler->zone(); |
| 5015 | 5015 |
| 5016 switch (type()) { | 5016 switch (assertion_type()) { |
| 5017 case START_OF_LINE: | 5017 case START_OF_LINE: |
| 5018 return AssertionNode::AfterNewline(on_success); | 5018 return AssertionNode::AfterNewline(on_success); |
| 5019 case START_OF_INPUT: | 5019 case START_OF_INPUT: |
| 5020 return AssertionNode::AtStart(on_success); | 5020 return AssertionNode::AtStart(on_success); |
| 5021 case BOUNDARY: | 5021 case BOUNDARY: |
| 5022 return AssertionNode::AtBoundary(on_success); | 5022 return AssertionNode::AtBoundary(on_success); |
| 5023 case NON_BOUNDARY: | 5023 case NON_BOUNDARY: |
| 5024 return AssertionNode::AtNonBoundary(on_success); | 5024 return AssertionNode::AtNonBoundary(on_success); |
| 5025 case END_OF_INPUT: | 5025 case END_OF_INPUT: |
| 5026 return AssertionNode::AtEnd(on_success); | 5026 return AssertionNode::AtEnd(on_success); |
| (...skipping 681 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5708 | 5708 |
| 5709 | 5709 |
| 5710 void TextNode::CalculateOffsets() { | 5710 void TextNode::CalculateOffsets() { |
| 5711 int element_count = elements()->length(); | 5711 int element_count = elements()->length(); |
| 5712 // Set up the offsets of the elements relative to the start. This is a fixed | 5712 // Set up the offsets of the elements relative to the start. This is a fixed |
| 5713 // quantity since a TextNode can only contain fixed-width things. | 5713 // quantity since a TextNode can only contain fixed-width things. |
| 5714 int cp_offset = 0; | 5714 int cp_offset = 0; |
| 5715 for (int i = 0; i < element_count; i++) { | 5715 for (int i = 0; i < element_count; i++) { |
| 5716 TextElement& elm = elements()->at(i); | 5716 TextElement& elm = elements()->at(i); |
| 5717 elm.cp_offset = cp_offset; | 5717 elm.cp_offset = cp_offset; |
| 5718 if (elm.type == TextElement::ATOM) { | 5718 if (elm.text_type == TextElement::ATOM) { |
| 5719 cp_offset += elm.data.u_atom->data().length(); | 5719 cp_offset += elm.data.u_atom->data().length(); |
| 5720 } else { | 5720 } else { |
| 5721 cp_offset++; | 5721 cp_offset++; |
| 5722 } | 5722 } |
| 5723 } | 5723 } |
| 5724 } | 5724 } |
| 5725 | 5725 |
| 5726 | 5726 |
| 5727 void Analysis::VisitText(TextNode* that) { | 5727 void Analysis::VisitText(TextNode* that) { |
| 5728 if (ignore_case_) { | 5728 if (ignore_case_) { |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5828 bool not_at_start) { | 5828 bool not_at_start) { |
| 5829 if (initial_offset >= bm->length()) return; | 5829 if (initial_offset >= bm->length()) return; |
| 5830 int offset = initial_offset; | 5830 int offset = initial_offset; |
| 5831 int max_char = bm->max_char(); | 5831 int max_char = bm->max_char(); |
| 5832 for (int i = 0; i < elements()->length(); i++) { | 5832 for (int i = 0; i < elements()->length(); i++) { |
| 5833 if (offset >= bm->length()) { | 5833 if (offset >= bm->length()) { |
| 5834 if (initial_offset == 0) set_bm_info(not_at_start, bm); | 5834 if (initial_offset == 0) set_bm_info(not_at_start, bm); |
| 5835 return; | 5835 return; |
| 5836 } | 5836 } |
| 5837 TextElement text = elements()->at(i); | 5837 TextElement text = elements()->at(i); |
| 5838 if (text.type == TextElement::ATOM) { | 5838 if (text.text_type == TextElement::ATOM) { |
| 5839 RegExpAtom* atom = text.data.u_atom; | 5839 RegExpAtom* atom = text.data.u_atom; |
| 5840 for (int j = 0; j < atom->length(); j++, offset++) { | 5840 for (int j = 0; j < atom->length(); j++, offset++) { |
| 5841 if (offset >= bm->length()) { | 5841 if (offset >= bm->length()) { |
| 5842 if (initial_offset == 0) set_bm_info(not_at_start, bm); | 5842 if (initial_offset == 0) set_bm_info(not_at_start, bm); |
| 5843 return; | 5843 return; |
| 5844 } | 5844 } |
| 5845 uc16 character = atom->data()[j]; | 5845 uc16 character = atom->data()[j]; |
| 5846 if (bm->compiler()->ignore_case()) { | 5846 if (bm->compiler()->ignore_case()) { |
| 5847 unibrow::uchar chars[unibrow::Ecma262UnCanonicalize::kMaxWidth]; | 5847 unibrow::uchar chars[unibrow::Ecma262UnCanonicalize::kMaxWidth]; |
| 5848 int length = GetCaseIndependentLetters( | 5848 int length = GetCaseIndependentLetters( |
| 5849 ISOLATE, | 5849 ISOLATE, |
| 5850 character, | 5850 character, |
| 5851 bm->max_char() == String::kMaxOneByteCharCode, | 5851 bm->max_char() == String::kMaxOneByteCharCode, |
| 5852 chars); | 5852 chars); |
| 5853 for (int j = 0; j < length; j++) { | 5853 for (int j = 0; j < length; j++) { |
| 5854 bm->Set(offset, chars[j]); | 5854 bm->Set(offset, chars[j]); |
| 5855 } | 5855 } |
| 5856 } else { | 5856 } else { |
| 5857 if (character <= max_char) bm->Set(offset, character); | 5857 if (character <= max_char) bm->Set(offset, character); |
| 5858 } | 5858 } |
| 5859 } | 5859 } |
| 5860 } else { | 5860 } else { |
| 5861 ASSERT(text.type == TextElement::CHAR_CLASS); | 5861 ASSERT(text.text_type == TextElement::CHAR_CLASS); |
| 5862 RegExpCharacterClass* char_class = text.data.u_char_class; | 5862 RegExpCharacterClass* char_class = text.data.u_char_class; |
| 5863 ZoneList<CharacterRange>* ranges = char_class->ranges(zone()); | 5863 ZoneList<CharacterRange>* ranges = char_class->ranges(zone()); |
| 5864 if (char_class->is_negated()) { | 5864 if (char_class->is_negated()) { |
| 5865 bm->SetAll(offset); | 5865 bm->SetAll(offset); |
| 5866 } else { | 5866 } else { |
| 5867 for (int k = 0; k < ranges->length(); k++) { | 5867 for (int k = 0; k < ranges->length(); k++) { |
| 5868 CharacterRange& range = ranges->at(k); | 5868 CharacterRange& range = ranges->at(k); |
| 5869 if (range.from() > max_char) continue; | 5869 if (range.from() > max_char) continue; |
| 5870 int to = Min(max_char, static_cast<int>(range.to())); | 5870 int to = Min(max_char, static_cast<int>(range.to())); |
| 5871 bm->SetInterval(offset, Interval(range.from(), to)); | 5871 bm->SetInterval(offset, Interval(range.from(), to)); |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5964 last = range.to() + 1; | 5964 last = range.to() + 1; |
| 5965 } | 5965 } |
| 5966 } | 5966 } |
| 5967 } | 5967 } |
| 5968 AddRange(CharacterRange(last, String::kMaxUtf16CodeUnit)); | 5968 AddRange(CharacterRange(last, String::kMaxUtf16CodeUnit)); |
| 5969 } | 5969 } |
| 5970 | 5970 |
| 5971 | 5971 |
| 5972 void DispatchTableConstructor::VisitText(TextNode* that) { | 5972 void DispatchTableConstructor::VisitText(TextNode* that) { |
| 5973 TextElement elm = that->elements()->at(0); | 5973 TextElement elm = that->elements()->at(0); |
| 5974 switch (elm.type) { | 5974 switch (elm.text_type) { |
| 5975 case TextElement::ATOM: { | 5975 case TextElement::ATOM: { |
| 5976 uc16 c = elm.data.u_atom->data()[0]; | 5976 uc16 c = elm.data.u_atom->data()[0]; |
| 5977 AddRange(CharacterRange(c, c)); | 5977 AddRange(CharacterRange(c, c)); |
| 5978 break; | 5978 break; |
| 5979 } | 5979 } |
| 5980 case TextElement::CHAR_CLASS: { | 5980 case TextElement::CHAR_CLASS: { |
| 5981 RegExpCharacterClass* tree = elm.data.u_char_class; | 5981 RegExpCharacterClass* tree = elm.data.u_char_class; |
| 5982 ZoneList<CharacterRange>* ranges = tree->ranges(that->zone()); | 5982 ZoneList<CharacterRange>* ranges = tree->ranges(that->zone()); |
| 5983 if (tree->is_negated()) { | 5983 if (tree->is_negated()) { |
| 5984 AddInverse(ranges); | 5984 AddInverse(ranges); |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6123 } | 6123 } |
| 6124 | 6124 |
| 6125 return compiler.Assemble(¯o_assembler, | 6125 return compiler.Assemble(¯o_assembler, |
| 6126 node, | 6126 node, |
| 6127 data->capture_count, | 6127 data->capture_count, |
| 6128 pattern); | 6128 pattern); |
| 6129 } | 6129 } |
| 6130 | 6130 |
| 6131 | 6131 |
| 6132 }} // namespace v8::internal | 6132 }} // namespace v8::internal |
| OLD | NEW |