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 |