Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1462)

Side by Side Diff: runtime/vm/regexp.cc

Issue 683433003: Integrate the Irregexp Regular Expression Engine. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: more comments Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/regexp.h ('k') | runtime/vm/regexp_assembler.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/regexp.h" 5 #include "vm/regexp.h"
6 6
7 // SNIP 7 #include "vm/dart_entry.h"
8 #include "vm/regexp_assembler.h"
9 #include "vm/regexp_ast.h"
10 #include "vm/unibrow-inl.h"
11 #include "vm/unicode.h"
12 #include "vm/symbols.h"
13
14 #define I (isolate())
15 #define CI (compiler->isolate())
8 16
9 namespace dart { 17 namespace dart {
10 18
11 // SNIP 19 DECLARE_FLAG(bool, trace_irregexp);
20
21 // Default to generating optimized regexp code.
22 static const bool kRegexpOptimization = true;
23
24 // More makes code generation slower, less makes V8 benchmark score lower.
25 static const intptr_t kMaxLookaheadForBoyerMoore = 8;
26
27 ContainedInLattice AddRange(ContainedInLattice containment,
28 const intptr_t* ranges,
29 intptr_t ranges_length,
30 Interval new_range) {
31 ASSERT((ranges_length & 1) == 1);
32 ASSERT(ranges[ranges_length - 1] == Utf16::kMaxCodeUnit + 1);
33 if (containment == kLatticeUnknown) return containment;
34 bool inside = false;
35 intptr_t last = 0;
36 for (intptr_t i = 0; i < ranges_length;
37 inside = !inside, last = ranges[i], i++) {
38 // Consider the range from last to ranges[i].
39 // We haven't got to the new range yet.
40 if (ranges[i] <= new_range.from()) continue;
41 // New range is wholly inside last-ranges[i]. Note that new_range.to() is
42 // inclusive, but the values in ranges are not.
43 if (last <= new_range.from() && new_range.to() < ranges[i]) {
44 return Combine(containment, inside ? kLatticeIn : kLatticeOut);
45 }
46 return kLatticeUnknown;
47 }
48 return containment;
49 }
12 50
13 // ------------------------------------------------------------------- 51 // -------------------------------------------------------------------
14 // Implementation of the Irregexp regular expression engine. 52 // Implementation of the Irregexp regular expression engine.
15 // 53 //
16 // The Irregexp regular expression engine is intended to be a complete 54 // The Irregexp regular expression engine is intended to be a complete
17 // implementation of ECMAScript regular expressions. It generates either 55 // implementation of ECMAScript regular expressions. It generates
18 // bytecodes or native code. 56 // IR code that is subsequently compiled to native code.
19 57
20 // The Irregexp regexp engine is structured in three steps. 58 // The Irregexp regexp engine is structured in three steps.
21 // 1) The parser generates an abstract syntax tree. See ast.cc. 59 // 1) The parser generates an abstract syntax tree. See regexp_ast.cc.
22 // 2) From the AST a node network is created. The nodes are all 60 // 2) From the AST a node network is created. The nodes are all
23 // subclasses of RegExpNode. The nodes represent states when 61 // subclasses of RegExpNode. The nodes represent states when
24 // executing a regular expression. Several optimizations are 62 // executing a regular expression. Several optimizations are
25 // performed on the node network. 63 // performed on the node network.
26 // 3) From the nodes we generate either byte codes or native code 64 // 3) From the nodes we generate IR instructions that can actually
27 // that can actually execute the regular expression (perform 65 // execute the regular expression (perform the search). The
28 // the search). The code generation step is described in more 66 // code generation step is described in more detail below.
29 // detail below.
30 67
31 // Code generation. 68 // Code generation.
32 // 69 //
33 // The nodes are divided into four main categories. 70 // The nodes are divided into four main categories.
34 // * Choice nodes 71 // * Choice nodes
35 // These represent places where the regular expression can 72 // These represent places where the regular expression can
36 // match in more than one way. For example on entry to an 73 // match in more than one way. For example on entry to an
37 // alternation (foo|bar) or a repetition (*, +, ? or {}). 74 // alternation (foo|bar) or a repetition (*, +, ? or {}).
38 // * Action nodes 75 // * Action nodes
39 // These represent places where some action should be 76 // These represent places where some action should be
40 // performed. Examples include recording the current position 77 // performed. Examples include recording the current position
41 // in the input string to a register (in order to implement 78 // in the input string to a register (in order to implement
42 // captures) or other actions on register for example in order 79 // captures) or other actions on register for example in order
43 // to implement the counters needed for {} repetitions. 80 // to implement the counters needed for {} repetitions.
44 // * Matching nodes 81 // * Matching nodes
45 // These attempt to match some element part of the input string. 82 // These attempt to match some element part of the input string.
46 // Examples of elements include character classes, plain strings 83 // Examples of elements include character classes, plain strings
47 // or back references. 84 // or back references.
48 // * End nodes 85 // * End nodes
49 // These are used to implement the actions required on finding 86 // These are used to implement the actions required on finding
50 // a successful match or failing to find a match. 87 // a successful match or failing to find a match.
51 // 88 //
52 // The code generated (whether as byte codes or native code) maintains 89 // The code generated maintains some state as it runs. This consists of the
53 // some state as it runs. This consists of the following elements: 90 // following elements:
54 // 91 //
55 // * The capture registers. Used for string captures. 92 // * The capture registers. Used for string captures.
56 // * Other registers. Used for counters etc. 93 // * Other registers. Used for counters etc.
57 // * The current position. 94 // * The current position.
58 // * The stack of backtracking information. Used when a matching node 95 // * The stack of backtracking information. Used when a matching node
59 // fails to find a match and needs to try an alternative. 96 // fails to find a match and needs to try an alternative.
60 // 97 //
61 // Conceptual regular expression execution model: 98 // Conceptual regular expression execution model:
62 // 99 //
63 // There is a simple conceptual model of regular expression execution 100 // There is a simple conceptual model of regular expression execution
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
153 // to that trace. The code generator therefore has the ability to generate 190 // to that trace. The code generator therefore has the ability to generate
154 // code for each node several times. In order to limit the size of the 191 // code for each node several times. In order to limit the size of the
155 // generated code there is an arbitrary limit on how many specialized sets of 192 // generated code there is an arbitrary limit on how many specialized sets of
156 // code may be generated for a given node. If the limit is reached, the 193 // code may be generated for a given node. If the limit is reached, the
157 // trace is flushed and a generic version of the code for a node is emitted. 194 // trace is flushed and a generic version of the code for a node is emitted.
158 // This is subsequently used for that node. The code emitted for non-generic 195 // This is subsequently used for that node. The code emitted for non-generic
159 // trace is not recorded in the node and so it cannot currently be reused in 196 // trace is not recorded in the node and so it cannot currently be reused in
160 // the event that code generation is requested for an identical trace. 197 // the event that code generation is requested for an identical trace.
161 198
162 199
163 void RegExpTree::AppendToText(RegExpText* text, Zone* zone) { 200 void RegExpTree::AppendToText(RegExpText* text) {
164 UNREACHABLE(); 201 UNREACHABLE();
165 } 202 }
166 203
167 204
168 void RegExpAtom::AppendToText(RegExpText* text, Zone* zone) { 205 void RegExpAtom::AppendToText(RegExpText* text) {
169 text->AddElement(TextElement::Atom(this), zone); 206 text->AddElement(TextElement::Atom(this));
170 } 207 }
171 208
172 209
173 void RegExpCharacterClass::AppendToText(RegExpText* text, Zone* zone) { 210 void RegExpCharacterClass::AppendToText(RegExpText* text) {
174 text->AddElement(TextElement::CharClass(this), zone); 211 text->AddElement(TextElement::CharClass(this));
175 } 212 }
176 213
177 214
178 void RegExpText::AppendToText(RegExpText* text, Zone* zone) { 215 void RegExpText::AppendToText(RegExpText* text) {
179 for (int i = 0; i < elements()->length(); i++) 216 for (intptr_t i = 0; i < elements()->length(); i++)
180 text->AddElement(elements()->at(i), zone); 217 text->AddElement((*elements())[i]);
181 } 218 }
182 219
183 220
184 TextElement TextElement::Atom(RegExpAtom* atom) { 221 TextElement TextElement::Atom(RegExpAtom* atom) {
185 return TextElement(ATOM, atom); 222 return TextElement(ATOM, atom);
186 } 223 }
187 224
188 225
189 TextElement TextElement::CharClass(RegExpCharacterClass* char_class) { 226 TextElement TextElement::CharClass(RegExpCharacterClass* char_class) {
190 return TextElement(CHAR_CLASS, char_class); 227 return TextElement(CHAR_CLASS, char_class);
191 } 228 }
192 229
193 230
194 int TextElement::length() const { 231 intptr_t TextElement::length() const {
195 switch (text_type()) { 232 switch (text_type()) {
196 case ATOM: 233 case ATOM:
197 return atom()->length(); 234 return atom()->length();
198 235
199 case CHAR_CLASS: 236 case CHAR_CLASS:
200 return 1; 237 return 1;
201 } 238 }
202 UNREACHABLE(); 239 UNREACHABLE();
203 return 0; 240 return 0;
204 } 241 }
205 242
206 243
207 DispatchTable* ChoiceNode::GetTable(bool ignore_case) { 244 class FrequencyCollator : public ValueObject {
208 if (table_ == NULL) {
209 table_ = new(zone()) DispatchTable(zone());
210 DispatchTableConstructor cons(table_, ignore_case, zone());
211 cons.BuildTable(this);
212 }
213 return table_;
214 }
215
216
217 class FrequencyCollator {
218 public: 245 public:
219 FrequencyCollator() : total_samples_(0) { 246 FrequencyCollator() : total_samples_(0) {
220 for (int i = 0; i < RegExpMacroAssembler::kTableSize; i++) { 247 for (intptr_t i = 0; i < RegExpMacroAssembler::kTableSize; i++) {
221 frequencies_[i] = CharacterFrequency(i); 248 frequencies_[i] = CharacterFrequency(i);
222 } 249 }
223 } 250 }
224 251
225 void CountCharacter(int character) { 252 void CountCharacter(intptr_t character) {
226 int index = (character & RegExpMacroAssembler::kTableMask); 253 intptr_t index = (character & RegExpMacroAssembler::kTableMask);
227 frequencies_[index].Increment(); 254 frequencies_[index].Increment();
228 total_samples_++; 255 total_samples_++;
229 } 256 }
230 257
231 // Does not measure in percent, but rather per-128 (the table size from the 258 // Does not measure in percent, but rather per-128 (the table size from the
232 // regexp macro assembler). 259 // regexp macro assembler).
233 int Frequency(int in_character) { 260 intptr_t Frequency(intptr_t in_character) {
234 DCHECK((in_character & RegExpMacroAssembler::kTableMask) == in_character); 261 ASSERT((in_character & RegExpMacroAssembler::kTableMask) == in_character);
235 if (total_samples_ < 1) return 1; // Division by zero. 262 if (total_samples_ < 1) return 1; // Division by zero.
236 int freq_in_per128 = 263 intptr_t freq_in_per128 =
237 (frequencies_[in_character].counter() * 128) / total_samples_; 264 (frequencies_[in_character].counter() * 128) / total_samples_;
238 return freq_in_per128; 265 return freq_in_per128;
239 } 266 }
240 267
241 private: 268 private:
242 class CharacterFrequency { 269 class CharacterFrequency {
243 public: 270 public:
244 CharacterFrequency() : counter_(0), character_(-1) { } 271 CharacterFrequency() : counter_(0), character_(-1) { }
245 explicit CharacterFrequency(int character) 272 explicit CharacterFrequency(intptr_t character)
246 : counter_(0), character_(character) { } 273 : counter_(0), character_(character) { }
247 274
248 void Increment() { counter_++; } 275 void Increment() { counter_++; }
249 int counter() { return counter_; } 276 intptr_t counter() { return counter_; }
250 int character() { return character_; } 277 intptr_t character() { return character_; }
251 278
252 private: 279 private:
253 int counter_; 280 intptr_t counter_;
254 int character_; 281 intptr_t character_;
282
283 DISALLOW_ALLOCATION();
255 }; 284 };
256 285
257 286
258 private: 287 private:
259 CharacterFrequency frequencies_[RegExpMacroAssembler::kTableSize]; 288 CharacterFrequency frequencies_[RegExpMacroAssembler::kTableSize];
260 int total_samples_; 289 intptr_t total_samples_;
261 }; 290 };
262 291
263 292
264 class RegExpCompiler { 293 class RegExpCompiler : public ValueObject {
265 public: 294 public:
266 RegExpCompiler(int capture_count, bool ignore_case, bool is_one_byte, 295 RegExpCompiler(intptr_t capture_count,
267 Zone* zone); 296 bool ignore_case,
297 intptr_t specialization_cid);
268 298
269 int AllocateRegister() { 299 intptr_t AllocateRegister() {
270 if (next_register_ >= RegExpMacroAssembler::kMaxRegister) {
271 reg_exp_too_big_ = true;
272 return next_register_;
273 }
274 return next_register_++; 300 return next_register_++;
275 } 301 }
276 302
277 RegExpEngine::CompilationResult Assemble(RegExpMacroAssembler* assembler, 303 RegExpEngine::CompilationResult Assemble(IRRegExpMacroAssembler* assembler,
278 RegExpNode* start, 304 RegExpNode* start,
279 int capture_count, 305 intptr_t capture_count,
280 Handle<String> pattern); 306 const String& pattern);
281 307
282 inline void AddWork(RegExpNode* node) { work_list_->Add(node); } 308 inline void AddWork(RegExpNode* node) { work_list_->Add(node); }
283 309
284 static const int kImplementationOffset = 0; 310 static const intptr_t kImplementationOffset = 0;
285 static const int kNumberOfRegistersOffset = 0; 311 static const intptr_t kNumberOfRegistersOffset = 0;
286 static const int kCodeOffset = 1; 312 static const intptr_t kCodeOffset = 1;
287 313
288 RegExpMacroAssembler* macro_assembler() { return macro_assembler_; } 314 IRRegExpMacroAssembler* macro_assembler() { return macro_assembler_; }
289 EndNode* accept() { return accept_; } 315 EndNode* accept() { return accept_; }
290 316
291 static const int kMaxRecursion = 100; 317 static const intptr_t kMaxRecursion = 100;
292 inline int recursion_depth() { return recursion_depth_; } 318 inline intptr_t recursion_depth() { return recursion_depth_; }
293 inline void IncrementRecursionDepth() { recursion_depth_++; } 319 inline void IncrementRecursionDepth() { recursion_depth_++; }
294 inline void DecrementRecursionDepth() { recursion_depth_--; } 320 inline void DecrementRecursionDepth() { recursion_depth_--; }
295 321
296 void SetRegExpTooBig() { reg_exp_too_big_ = true; } 322 void SetRegExpTooBig() { reg_exp_too_big_ = true; }
297 323
298 inline bool ignore_case() { return ignore_case_; } 324 inline bool ignore_case() { return ignore_case_; }
299 inline bool one_byte() { return one_byte_; } 325 inline bool one_byte() const {
326 return (specialization_cid_ == kOneByteStringCid ||
327 specialization_cid_ == kExternalOneByteStringCid);
328 }
329 inline intptr_t specialization_cid() { return specialization_cid_; }
300 FrequencyCollator* frequency_collator() { return &frequency_collator_; } 330 FrequencyCollator* frequency_collator() { return &frequency_collator_; }
301 331
302 int current_expansion_factor() { return current_expansion_factor_; } 332 intptr_t current_expansion_factor() { return current_expansion_factor_; }
303 void set_current_expansion_factor(int value) { 333 void set_current_expansion_factor(intptr_t value) {
304 current_expansion_factor_ = value; 334 current_expansion_factor_ = value;
305 } 335 }
306 336
307 Zone* zone() const { return zone_; } 337 Isolate* isolate() const { return isolate_; }
308 338
309 static const int kNoRegister = -1; 339 static const intptr_t kNoRegister = -1;
310 340
311 private: 341 private:
312 EndNode* accept_; 342 EndNode* accept_;
313 int next_register_; 343 intptr_t next_register_;
314 List<RegExpNode*>* work_list_; 344 ZoneGrowableArray<RegExpNode*>* work_list_;
315 int recursion_depth_; 345 intptr_t recursion_depth_;
316 RegExpMacroAssembler* macro_assembler_; 346 IRRegExpMacroAssembler* macro_assembler_;
317 bool ignore_case_; 347 bool ignore_case_;
318 bool one_byte_; 348 intptr_t specialization_cid_;
319 bool reg_exp_too_big_; 349 bool reg_exp_too_big_;
320 int current_expansion_factor_; 350 intptr_t current_expansion_factor_;
321 FrequencyCollator frequency_collator_; 351 FrequencyCollator frequency_collator_;
322 Zone* zone_; 352 Isolate* isolate_;
323 }; 353 };
324 354
325 355
326 class RecursionCheck { 356 class RecursionCheck : public ValueObject {
327 public: 357 public:
328 explicit RecursionCheck(RegExpCompiler* compiler) : compiler_(compiler) { 358 explicit RecursionCheck(RegExpCompiler* compiler) : compiler_(compiler) {
329 compiler->IncrementRecursionDepth(); 359 compiler->IncrementRecursionDepth();
330 } 360 }
331 ~RecursionCheck() { compiler_->DecrementRecursionDepth(); } 361 ~RecursionCheck() { compiler_->DecrementRecursionDepth(); }
332 private: 362 private:
333 RegExpCompiler* compiler_; 363 RegExpCompiler* compiler_;
334 }; 364 };
335 365
336 366
337 static RegExpEngine::CompilationResult IrregexpRegExpTooBig(Isolate* isolate) { 367 static RegExpEngine::CompilationResult IrregexpRegExpTooBig() {
338 return RegExpEngine::CompilationResult(isolate, "RegExp too big"); 368 return RegExpEngine::CompilationResult("RegExp too big");
339 } 369 }
340 370
341 371
342 // Attempts to compile the regexp using an Irregexp code generator. Returns 372 // Attempts to compile the regexp using an Irregexp code generator. Returns
343 // a fixed array or a null handle depending on whether it succeeded. 373 // a fixed array or a null handle depending on whether it succeeded.
344 RegExpCompiler::RegExpCompiler(int capture_count, bool ignore_case, 374 RegExpCompiler::RegExpCompiler(intptr_t capture_count, bool ignore_case,
345 bool one_byte, Zone* zone) 375 intptr_t specialization_cid)
346 : next_register_(2 * (capture_count + 1)), 376 : next_register_(2 * (capture_count + 1)),
347 work_list_(NULL), 377 work_list_(NULL),
348 recursion_depth_(0), 378 recursion_depth_(0),
349 ignore_case_(ignore_case), 379 ignore_case_(ignore_case),
350 one_byte_(one_byte), 380 specialization_cid_(specialization_cid),
351 reg_exp_too_big_(false), 381 reg_exp_too_big_(false),
352 current_expansion_factor_(1), 382 current_expansion_factor_(1),
353 frequency_collator_(), 383 isolate_(Isolate::Current()) {
354 zone_(zone) { 384 accept_ = new(I) EndNode(EndNode::ACCEPT, I);
355 accept_ = new(zone) EndNode(EndNode::ACCEPT, zone);
356 DCHECK(next_register_ - 1 <= RegExpMacroAssembler::kMaxRegister);
357 } 385 }
358 386
359 387
360 RegExpEngine::CompilationResult RegExpCompiler::Assemble( 388 RegExpEngine::CompilationResult RegExpCompiler::Assemble(
361 RegExpMacroAssembler* macro_assembler, 389 IRRegExpMacroAssembler* macro_assembler,
362 RegExpNode* start, 390 RegExpNode* start,
363 int capture_count, 391 intptr_t capture_count,
364 Handle<String> pattern) { 392 const String& pattern) {
365 Heap* heap = pattern->GetHeap(); 393 static const bool use_slow_safe_regexp_compiler = false;
366
367 bool use_slow_safe_regexp_compiler = false;
368 if (heap->total_regexp_code_generated() >
369 RegExpImpl::kRegWxpCompiledLimit &&
370 heap->isolate()->memory_allocator()->SizeExecutable() >
371 RegExpImpl::kRegExpExecutableMemoryLimit) {
372 use_slow_safe_regexp_compiler = true;
373 }
374 394
375 macro_assembler->set_slow_safe(use_slow_safe_regexp_compiler); 395 macro_assembler->set_slow_safe(use_slow_safe_regexp_compiler);
396 macro_assembler_ = macro_assembler;
376 397
377 #ifdef DEBUG 398 ZoneGrowableArray<RegExpNode*> work_list(0);
378 if (FLAG_trace_regexp_assembler)
379 macro_assembler_ = new RegExpMacroAssemblerTracer(macro_assembler);
380 else
381 #endif
382 macro_assembler_ = macro_assembler;
383
384 List <RegExpNode*> work_list(0);
385 work_list_ = &work_list; 399 work_list_ = &work_list;
386 Label fail; 400 BlockLabel fail;
387 macro_assembler_->PushBacktrack(&fail); 401 macro_assembler_->PushBacktrack(&fail);
388 Trace new_trace; 402 Trace new_trace;
389 start->Emit(this, &new_trace); 403 start->Emit(this, &new_trace);
390 macro_assembler_->Bind(&fail); 404 macro_assembler_->BindBlock(&fail);
391 macro_assembler_->Fail(); 405 macro_assembler_->Fail();
392 while (!work_list.is_empty()) { 406 while (!work_list.is_empty()) {
393 work_list.RemoveLast()->Emit(this, &new_trace); 407 work_list.RemoveLast()->Emit(this, &new_trace);
394 } 408 }
395 if (reg_exp_too_big_) return IrregexpRegExpTooBig(zone_->isolate()); 409 if (reg_exp_too_big_) return IrregexpRegExpTooBig();
396 410
397 Handle<HeapObject> code = macro_assembler_->GetCode(pattern); 411 macro_assembler->FinalizeIndirectGotos();
398 heap->IncreaseTotalRegexpCodeGenerated(code->Size()); 412
399 work_list_ = NULL; 413 return RegExpEngine::CompilationResult(macro_assembler,
400 #ifdef DEBUG 414 macro_assembler->graph_entry(),
401 if (FLAG_print_code) { 415 macro_assembler->num_blocks(),
402 CodeTracer::Scope trace_scope(heap->isolate()->GetCodeTracer()); 416 macro_assembler->num_stack_locals());
403 OFStream os(trace_scope.file());
404 Handle<Code>::cast(code)->Disassemble(pattern->ToCString().get(), os);
405 }
406 if (FLAG_trace_regexp_assembler) {
407 delete macro_assembler_;
408 }
409 #endif
410 return RegExpEngine::CompilationResult(*code, next_register_);
411 } 417 }
412 418
413 419
414 bool Trace::DeferredAction::Mentions(int that) { 420 bool Trace::DeferredAction::Mentions(intptr_t that) {
415 if (action_type() == ActionNode::CLEAR_CAPTURES) { 421 if (action_type() == ActionNode::CLEAR_CAPTURES) {
416 Interval range = static_cast<DeferredClearCaptures*>(this)->range(); 422 Interval range = static_cast<DeferredClearCaptures*>(this)->range();
417 return range.Contains(that); 423 return range.Contains(that);
418 } else { 424 } else {
419 return reg() == that; 425 return reg() == that;
420 } 426 }
421 } 427 }
422 428
423 429
424 bool Trace::mentions_reg(int reg) { 430 bool Trace::mentions_reg(intptr_t reg) {
425 for (DeferredAction* action = actions_; 431 for (DeferredAction* action = actions_;
426 action != NULL; 432 action != NULL;
427 action = action->next()) { 433 action = action->next()) {
428 if (action->Mentions(reg)) 434 if (action->Mentions(reg))
429 return true; 435 return true;
430 } 436 }
431 return false; 437 return false;
432 } 438 }
433 439
434 440
435 bool Trace::GetStoredPosition(int reg, int* cp_offset) { 441 bool Trace::GetStoredPosition(intptr_t reg, intptr_t* cp_offset) {
436 DCHECK_EQ(0, *cp_offset); 442 ASSERT(*cp_offset == 0);
437 for (DeferredAction* action = actions_; 443 for (DeferredAction* action = actions_;
438 action != NULL; 444 action != NULL;
439 action = action->next()) { 445 action = action->next()) {
440 if (action->Mentions(reg)) { 446 if (action->Mentions(reg)) {
441 if (action->action_type() == ActionNode::STORE_POSITION) { 447 if (action->action_type() == ActionNode::STORE_POSITION) {
442 *cp_offset = static_cast<DeferredCapture*>(action)->cp_offset(); 448 *cp_offset = static_cast<DeferredCapture*>(action)->cp_offset();
443 return true; 449 return true;
444 } else { 450 } else {
445 return false; 451 return false;
446 } 452 }
447 } 453 }
448 } 454 }
449 return false; 455 return false;
450 } 456 }
451 457
452 458
453 int Trace::FindAffectedRegisters(OutSet* affected_registers, 459 // This is called as we come into a loop choice node and some other tricky
454 Zone* zone) { 460 // nodes. It normalizes the state of the code generator to ensure we can
455 int max_register = RegExpCompiler::kNoRegister; 461 // generate generic code.
462 intptr_t Trace::FindAffectedRegisters(OutSet* affected_registers,
463 Isolate* isolate) {
464 intptr_t max_register = RegExpCompiler::kNoRegister;
456 for (DeferredAction* action = actions_; 465 for (DeferredAction* action = actions_;
457 action != NULL; 466 action != NULL;
458 action = action->next()) { 467 action = action->next()) {
459 if (action->action_type() == ActionNode::CLEAR_CAPTURES) { 468 if (action->action_type() == ActionNode::CLEAR_CAPTURES) {
460 Interval range = static_cast<DeferredClearCaptures*>(action)->range(); 469 Interval range = static_cast<DeferredClearCaptures*>(action)->range();
461 for (int i = range.from(); i <= range.to(); i++) 470 for (intptr_t i = range.from(); i <= range.to(); i++)
462 affected_registers->Set(i, zone); 471 affected_registers->Set(i, isolate);
463 if (range.to() > max_register) max_register = range.to(); 472 if (range.to() > max_register) max_register = range.to();
464 } else { 473 } else {
465 affected_registers->Set(action->reg(), zone); 474 affected_registers->Set(action->reg(), isolate);
466 if (action->reg() > max_register) max_register = action->reg(); 475 if (action->reg() > max_register) max_register = action->reg();
467 } 476 }
468 } 477 }
469 return max_register; 478 return max_register;
470 } 479 }
471 480
472 481
473 void Trace::RestoreAffectedRegisters(RegExpMacroAssembler* assembler, 482 void Trace::RestoreAffectedRegisters(RegExpMacroAssembler* assembler,
474 int max_register, 483 intptr_t max_register,
475 const OutSet& registers_to_pop, 484 const OutSet& registers_to_pop,
476 const OutSet& registers_to_clear) { 485 const OutSet& registers_to_clear) {
477 for (int reg = max_register; reg >= 0; reg--) { 486 for (intptr_t reg = max_register; reg >= 0; reg--) {
478 if (registers_to_pop.Get(reg)) { 487 if (registers_to_pop.Get(reg)) {
479 assembler->PopRegister(reg); 488 assembler->PopRegister(reg);
480 } else if (registers_to_clear.Get(reg)) { 489 } else if (registers_to_clear.Get(reg)) {
481 int clear_to = reg; 490 intptr_t clear_to = reg;
482 while (reg > 0 && registers_to_clear.Get(reg - 1)) { 491 while (reg > 0 && registers_to_clear.Get(reg - 1)) {
483 reg--; 492 reg--;
484 } 493 }
485 assembler->ClearRegisters(reg, clear_to); 494 assembler->ClearRegisters(reg, clear_to);
486 } 495 }
487 } 496 }
488 } 497 }
489 498
490 499
491 void Trace::PerformDeferredActions(RegExpMacroAssembler* assembler, 500 void Trace::PerformDeferredActions(RegExpMacroAssembler* assembler,
492 int max_register, 501 intptr_t max_register,
493 const OutSet& affected_registers, 502 const OutSet& affected_registers,
494 OutSet* registers_to_pop, 503 OutSet* registers_to_pop,
495 OutSet* registers_to_clear, 504 OutSet* registers_to_clear,
496 Zone* zone) { 505 Isolate* isolate) {
497 // The "+1" is to avoid a push_limit of zero if stack_limit_slack() is 1. 506 for (intptr_t reg = 0; reg <= max_register; reg++) {
498 const int push_limit = (assembler->stack_limit_slack() + 1) / 2;
499
500 // Count pushes performed to force a stack limit check occasionally.
501 int pushes = 0;
502
503 for (int reg = 0; reg <= max_register; reg++) {
504 if (!affected_registers.Get(reg)) { 507 if (!affected_registers.Get(reg)) {
505 continue; 508 continue;
506 } 509 }
507 510
508 // The chronologically first deferred action in the trace 511 // The chronologically first deferred action in the trace
509 // is used to infer the action needed to restore a register 512 // is used to infer the action needed to restore a register
510 // to its previous state (or not, if it's safe to ignore it). 513 // to its previous state (or not, if it's safe to ignore it).
511 enum DeferredActionUndoType { IGNORE, RESTORE, CLEAR }; 514 enum DeferredActionUndoType { IGNORE, RESTORE, CLEAR };
512 DeferredActionUndoType undo_action = IGNORE; 515 DeferredActionUndoType undo_action = IGNORE;
513 516
514 int value = 0; 517 intptr_t value = 0;
515 bool absolute = false; 518 bool absolute = false;
516 bool clear = false; 519 bool clear = false;
517 int store_position = -1; 520 intptr_t store_position = -1;
518 // This is a little tricky because we are scanning the actions in reverse 521 // This is a little tricky because we are scanning the actions in reverse
519 // historical order (newest first). 522 // historical order (newest first).
520 for (DeferredAction* action = actions_; 523 for (DeferredAction* action = actions_;
521 action != NULL; 524 action != NULL;
522 action = action->next()) { 525 action = action->next()) {
523 if (action->Mentions(reg)) { 526 if (action->Mentions(reg)) {
524 switch (action->action_type()) { 527 switch (action->action_type()) {
525 case ActionNode::SET_REGISTER: { 528 case ActionNode::SET_REGISTER: {
526 Trace::DeferredSetRegister* psr = 529 Trace::DeferredSetRegister* psr =
527 static_cast<Trace::DeferredSetRegister*>(action); 530 static_cast<Trace::DeferredSetRegister*>(action);
528 if (!absolute) { 531 if (!absolute) {
529 value += psr->value(); 532 value += psr->value();
530 absolute = true; 533 absolute = true;
531 } 534 }
532 // SET_REGISTER is currently only used for newly introduced loop 535 // SET_REGISTER is currently only used for newly introduced loop
533 // counters. They can have a significant previous value if they 536 // counters. They can have a significant previous value if they
534 // occour in a loop. TODO(lrn): Propagate this information, so 537 // occour in a loop. TODO(lrn): Propagate this information, so
535 // we can set undo_action to IGNORE if we know there is no value to 538 // we can set undo_action to IGNORE if we know there is no value to
536 // restore. 539 // restore.
537 undo_action = RESTORE; 540 undo_action = RESTORE;
538 DCHECK_EQ(store_position, -1); 541 ASSERT(store_position == -1);
539 DCHECK(!clear); 542 ASSERT(!clear);
540 break; 543 break;
541 } 544 }
542 case ActionNode::INCREMENT_REGISTER: 545 case ActionNode::INCREMENT_REGISTER:
543 if (!absolute) { 546 if (!absolute) {
544 value++; 547 value++;
545 } 548 }
546 DCHECK_EQ(store_position, -1); 549 ASSERT(store_position == -1);
547 DCHECK(!clear); 550 ASSERT(!clear);
548 undo_action = RESTORE; 551 undo_action = RESTORE;
549 break; 552 break;
550 case ActionNode::STORE_POSITION: { 553 case ActionNode::STORE_POSITION: {
551 Trace::DeferredCapture* pc = 554 Trace::DeferredCapture* pc =
552 static_cast<Trace::DeferredCapture*>(action); 555 static_cast<Trace::DeferredCapture*>(action);
553 if (!clear && store_position == -1) { 556 if (!clear && store_position == -1) {
554 store_position = pc->cp_offset(); 557 store_position = pc->cp_offset();
555 } 558 }
556 559
557 // For captures we know that stores and clears alternate. 560 // For captures we know that stores and clears alternate.
558 // Other register, are never cleared, and if the occur 561 // Other register, are never cleared, and if the occur
559 // inside a loop, they might be assigned more than once. 562 // inside a loop, they might be assigned more than once.
560 if (reg <= 1) { 563 if (reg <= 1) {
561 // Registers zero and one, aka "capture zero", is 564 // Registers zero and one, aka "capture zero", is
562 // always set correctly if we succeed. There is no 565 // always set correctly if we succeed. There is no
563 // need to undo a setting on backtrack, because we 566 // need to undo a setting on backtrack, because we
564 // will set it again or fail. 567 // will set it again or fail.
565 undo_action = IGNORE; 568 undo_action = IGNORE;
566 } else { 569 } else {
567 undo_action = pc->is_capture() ? CLEAR : RESTORE; 570 undo_action = pc->is_capture() ? CLEAR : RESTORE;
568 } 571 }
569 DCHECK(!absolute); 572 ASSERT(!absolute);
570 DCHECK_EQ(value, 0); 573 ASSERT(value == 0);
571 break; 574 break;
572 } 575 }
573 case ActionNode::CLEAR_CAPTURES: { 576 case ActionNode::CLEAR_CAPTURES: {
574 // Since we're scanning in reverse order, if we've already 577 // Since we're scanning in reverse order, if we've already
575 // set the position we have to ignore historically earlier 578 // set the position we have to ignore historically earlier
576 // clearing operations. 579 // clearing operations.
577 if (store_position == -1) { 580 if (store_position == -1) {
578 clear = true; 581 clear = true;
579 } 582 }
580 undo_action = RESTORE; 583 undo_action = RESTORE;
581 DCHECK(!absolute); 584 ASSERT(!absolute);
582 DCHECK_EQ(value, 0); 585 ASSERT(value == 0);
583 break; 586 break;
584 } 587 }
585 default: 588 default:
586 UNREACHABLE(); 589 UNREACHABLE();
587 break; 590 break;
588 } 591 }
589 } 592 }
590 } 593 }
591 // Prepare for the undo-action (e.g., push if it's going to be popped). 594 // Prepare for the undo-action (e.g., push if it's going to be popped).
592 if (undo_action == RESTORE) { 595 if (undo_action == RESTORE) {
593 pushes++; 596 assembler->PushRegister(reg);
594 RegExpMacroAssembler::StackCheckFlag stack_check = 597 registers_to_pop->Set(reg, isolate);
595 RegExpMacroAssembler::kNoStackLimitCheck;
596 if (pushes == push_limit) {
597 stack_check = RegExpMacroAssembler::kCheckStackLimit;
598 pushes = 0;
599 }
600
601 assembler->PushRegister(reg, stack_check);
602 registers_to_pop->Set(reg, zone);
603 } else if (undo_action == CLEAR) { 598 } else if (undo_action == CLEAR) {
604 registers_to_clear->Set(reg, zone); 599 registers_to_clear->Set(reg, isolate);
605 } 600 }
606 // Perform the chronologically last action (or accumulated increment) 601 // Perform the chronologically last action (or accumulated increment)
607 // for the register. 602 // for the register.
608 if (store_position != -1) { 603 if (store_position != -1) {
609 assembler->WriteCurrentPositionToRegister(reg, store_position); 604 assembler->WriteCurrentPositionToRegister(reg, store_position);
610 } else if (clear) { 605 } else if (clear) {
611 assembler->ClearRegisters(reg, reg); 606 assembler->ClearRegisters(reg, reg);
612 } else if (absolute) { 607 } else if (absolute) {
613 assembler->SetRegister(reg, value); 608 assembler->SetRegister(reg, value);
614 } else if (value != 0) { 609 } else if (value != 0) {
615 assembler->AdvanceRegister(reg, value); 610 assembler->AdvanceRegister(reg, value);
616 } 611 }
617 } 612 }
618 } 613 }
619 614
620 615
621 // This is called as we come into a loop choice node and some other tricky 616 // This is called as we come into a loop choice node and some other tricky
622 // nodes. It normalizes the state of the code generator to ensure we can 617 // nodes. It normalizes the state of the code generator to ensure we can
623 // generate generic code. 618 // generate generic code.
624 void Trace::Flush(RegExpCompiler* compiler, RegExpNode* successor) { 619 void Trace::Flush(RegExpCompiler* compiler, RegExpNode* successor) {
625 RegExpMacroAssembler* assembler = compiler->macro_assembler(); 620 RegExpMacroAssembler* assembler = compiler->macro_assembler();
626 621
627 DCHECK(!is_trivial()); 622 ASSERT(!is_trivial());
628 623
629 if (actions_ == NULL && backtrack() == NULL) { 624 if (actions_ == NULL && backtrack() == NULL) {
630 // Here we just have some deferred cp advances to fix and we are back to 625 // Here we just have some deferred cp advances to fix and we are back to
631 // a normal situation. We may also have to forget some information gained 626 // a normal situation. We may also have to forget some information gained
632 // through a quick check that was already performed. 627 // through a quick check that was already performed.
633 if (cp_offset_ != 0) assembler->AdvanceCurrentPosition(cp_offset_); 628 if (cp_offset_ != 0) assembler->AdvanceCurrentPosition(cp_offset_);
634 // Create a new trivial state and generate the node with that. 629 // Create a new trivial state and generate the node with that.
635 Trace new_state; 630 Trace new_state;
636 successor->Emit(compiler, &new_state); 631 successor->Emit(compiler, &new_state);
637 return; 632 return;
638 } 633 }
639 634
640 // Generate deferred actions here along with code to undo them again. 635 // Generate deferred actions here along with code to undo them again.
641 OutSet affected_registers; 636 OutSet affected_registers;
642 637
643 if (backtrack() != NULL) { 638 if (backtrack() != NULL) {
644 // Here we have a concrete backtrack location. These are set up by choice 639 // Here we have a concrete backtrack location. These are set up by choice
645 // nodes and so they indicate that we have a deferred save of the current 640 // nodes and so they indicate that we have a deferred save of the current
646 // position which we may need to emit here. 641 // position which we may need to emit here.
647 assembler->PushCurrentPosition(); 642 assembler->PushCurrentPosition();
648 } 643 }
649 644
650 int max_register = FindAffectedRegisters(&affected_registers, 645 intptr_t max_register = FindAffectedRegisters(&affected_registers, CI);
651 compiler->zone());
652 OutSet registers_to_pop; 646 OutSet registers_to_pop;
653 OutSet registers_to_clear; 647 OutSet registers_to_clear;
654 PerformDeferredActions(assembler, 648 PerformDeferredActions(assembler,
655 max_register, 649 max_register,
656 affected_registers, 650 affected_registers,
657 &registers_to_pop, 651 &registers_to_pop,
658 &registers_to_clear, 652 &registers_to_clear,
659 compiler->zone()); 653 CI);
660 if (cp_offset_ != 0) { 654 if (cp_offset_ != 0) {
661 assembler->AdvanceCurrentPosition(cp_offset_); 655 assembler->AdvanceCurrentPosition(cp_offset_);
662 } 656 }
663 657
664 // Create a new trivial state and generate the node with that. 658 // Create a new trivial state and generate the node with that.
665 Label undo; 659 BlockLabel undo;
666 assembler->PushBacktrack(&undo); 660 assembler->PushBacktrack(&undo);
667 Trace new_state; 661 Trace new_state;
668 successor->Emit(compiler, &new_state); 662 successor->Emit(compiler, &new_state);
669 663
670 // On backtrack we need to restore state. 664 // On backtrack we need to restore state.
671 assembler->Bind(&undo); 665 assembler->BindBlock(&undo);
672 RestoreAffectedRegisters(assembler, 666 RestoreAffectedRegisters(assembler,
673 max_register, 667 max_register,
674 registers_to_pop, 668 registers_to_pop,
675 registers_to_clear); 669 registers_to_clear);
676 if (backtrack() == NULL) { 670 if (backtrack() == NULL) {
677 assembler->Backtrack(); 671 assembler->Backtrack();
678 } else { 672 } else {
679 assembler->PopCurrentPosition(); 673 assembler->PopCurrentPosition();
680 assembler->GoTo(backtrack()); 674 assembler->GoTo(backtrack());
681 } 675 }
682 } 676 }
683 677
684 678
685 void NegativeSubmatchSuccess::Emit(RegExpCompiler* compiler, Trace* trace) { 679 void NegativeSubmatchSuccess::Emit(RegExpCompiler* compiler, Trace* trace) {
686 RegExpMacroAssembler* assembler = compiler->macro_assembler(); 680 RegExpMacroAssembler* assembler = compiler->macro_assembler();
687 681
688 // Omit flushing the trace. We discard the entire stack frame anyway. 682 // Omit flushing the trace. We discard the entire stack frame anyway.
689 683
690 if (!label()->is_bound()) { 684 if (!label()->IsBound()) {
691 // We are completely independent of the trace, since we ignore it, 685 // We are completely independent of the trace, since we ignore it,
692 // so this code can be used as the generic version. 686 // so this code can be used as the generic version.
693 assembler->Bind(label()); 687 assembler->BindBlock(label());
694 } 688 }
695 689
696 // Throw away everything on the backtrack stack since the start 690 // Throw away everything on the backtrack stack since the start
697 // of the negative submatch and restore the character position. 691 // of the negative submatch and restore the character position.
698 assembler->ReadCurrentPositionFromRegister(current_position_register_); 692 assembler->ReadCurrentPositionFromRegister(current_position_register_);
699 assembler->ReadStackPointerFromRegister(stack_pointer_register_); 693 assembler->ReadStackPointerFromRegister(stack_pointer_register_);
700 if (clear_capture_count_ > 0) { 694 if (clear_capture_count_ > 0) {
701 // Clear any captures that might have been performed during the success 695 // Clear any captures that might have been performed during the success
702 // of the body of the negative look-ahead. 696 // of the body of the negative look-ahead.
703 int clear_capture_end = clear_capture_start_ + clear_capture_count_ - 1; 697 int clear_capture_end = clear_capture_start_ + clear_capture_count_ - 1;
704 assembler->ClearRegisters(clear_capture_start_, clear_capture_end); 698 assembler->ClearRegisters(clear_capture_start_, clear_capture_end);
705 } 699 }
706 // Now that we have unwound the stack we find at the top of the stack the 700 // Now that we have unwound the stack we find at the top of the stack the
707 // backtrack that the BeginSubmatch node got. 701 // backtrack that the BeginSubmatch node got.
708 assembler->Backtrack(); 702 assembler->Backtrack();
709 } 703 }
710 704
711 705
712 void EndNode::Emit(RegExpCompiler* compiler, Trace* trace) { 706 void EndNode::Emit(RegExpCompiler* compiler, Trace* trace) {
713 if (!trace->is_trivial()) { 707 if (!trace->is_trivial()) {
714 trace->Flush(compiler, this); 708 trace->Flush(compiler, this);
715 return; 709 return;
716 } 710 }
717 RegExpMacroAssembler* assembler = compiler->macro_assembler(); 711 RegExpMacroAssembler* assembler = compiler->macro_assembler();
718 if (!label()->is_bound()) { 712 if (!label()->IsBound()) {
719 assembler->Bind(label()); 713 assembler->BindBlock(label());
720 } 714 }
721 switch (action_) { 715 switch (action_) {
722 case ACCEPT: 716 case ACCEPT:
723 assembler->Succeed(); 717 assembler->Succeed();
724 return; 718 return;
725 case BACKTRACK: 719 case BACKTRACK:
726 assembler->GoTo(trace->backtrack()); 720 assembler->GoTo(trace->backtrack());
727 return; 721 return;
728 case NEGATIVE_SUBMATCH_SUCCESS: 722 case NEGATIVE_SUBMATCH_SUCCESS:
729 // This case is handled in a different virtual method. 723 // This case is handled in a different virtual method.
730 UNREACHABLE(); 724 UNREACHABLE();
731 } 725 }
732 UNIMPLEMENTED(); 726 UNIMPLEMENTED();
733 } 727 }
734 728
735 729
736 void GuardedAlternative::AddGuard(Guard* guard, Zone* zone) { 730 void GuardedAlternative::AddGuard(Guard* guard, Isolate* isolate) {
737 if (guards_ == NULL) 731 if (guards_ == NULL)
738 guards_ = new(zone) ZoneList<Guard*>(1, zone); 732 guards_ = new(isolate) ZoneGrowableArray<Guard*>(1);
739 guards_->Add(guard, zone); 733 guards_->Add(guard);
740 } 734 }
741 735
742 736
743 ActionNode* ActionNode::SetRegister(int reg, 737 ActionNode* ActionNode::SetRegister(intptr_t reg,
744 int val, 738 intptr_t val,
745 RegExpNode* on_success) { 739 RegExpNode* on_success) {
746 ActionNode* result = 740 ActionNode* result =
747 new(on_success->zone()) ActionNode(SET_REGISTER, on_success); 741 new(on_success->isolate()) ActionNode(SET_REGISTER, on_success);
748 result->data_.u_store_register.reg = reg; 742 result->data_.u_store_register.reg = reg;
749 result->data_.u_store_register.value = val; 743 result->data_.u_store_register.value = val;
750 return result; 744 return result;
751 } 745 }
752 746
753 747
754 ActionNode* ActionNode::IncrementRegister(int reg, RegExpNode* on_success) { 748 ActionNode* ActionNode::IncrementRegister(intptr_t reg,
749 RegExpNode* on_success) {
755 ActionNode* result = 750 ActionNode* result =
756 new(on_success->zone()) ActionNode(INCREMENT_REGISTER, on_success); 751 new(on_success->isolate()) ActionNode(INCREMENT_REGISTER, on_success);
757 result->data_.u_increment_register.reg = reg; 752 result->data_.u_increment_register.reg = reg;
758 return result; 753 return result;
759 } 754 }
760 755
761 756
762 ActionNode* ActionNode::StorePosition(int reg, 757 ActionNode* ActionNode::StorePosition(intptr_t reg,
763 bool is_capture, 758 bool is_capture,
764 RegExpNode* on_success) { 759 RegExpNode* on_success) {
765 ActionNode* result = 760 ActionNode* result =
766 new(on_success->zone()) ActionNode(STORE_POSITION, on_success); 761 new(on_success->isolate()) ActionNode(STORE_POSITION, on_success);
767 result->data_.u_position_register.reg = reg; 762 result->data_.u_position_register.reg = reg;
768 result->data_.u_position_register.is_capture = is_capture; 763 result->data_.u_position_register.is_capture = is_capture;
769 return result; 764 return result;
770 } 765 }
771 766
772 767
773 ActionNode* ActionNode::ClearCaptures(Interval range, 768 ActionNode* ActionNode::ClearCaptures(Interval range,
774 RegExpNode* on_success) { 769 RegExpNode* on_success) {
775 ActionNode* result = 770 ActionNode* result =
776 new(on_success->zone()) ActionNode(CLEAR_CAPTURES, on_success); 771 new(on_success->isolate()) ActionNode(CLEAR_CAPTURES, on_success);
777 result->data_.u_clear_captures.range_from = range.from(); 772 result->data_.u_clear_captures.range_from = range.from();
778 result->data_.u_clear_captures.range_to = range.to(); 773 result->data_.u_clear_captures.range_to = range.to();
779 return result; 774 return result;
780 } 775 }
781 776
782 777
783 ActionNode* ActionNode::BeginSubmatch(int stack_reg, 778 ActionNode* ActionNode::BeginSubmatch(intptr_t stack_reg,
784 int position_reg, 779 intptr_t position_reg,
785 RegExpNode* on_success) { 780 RegExpNode* on_success) {
786 ActionNode* result = 781 ActionNode* result =
787 new(on_success->zone()) ActionNode(BEGIN_SUBMATCH, on_success); 782 new(on_success->isolate()) ActionNode(BEGIN_SUBMATCH, on_success);
788 result->data_.u_submatch.stack_pointer_register = stack_reg; 783 result->data_.u_submatch.stack_pointer_register = stack_reg;
789 result->data_.u_submatch.current_position_register = position_reg; 784 result->data_.u_submatch.current_position_register = position_reg;
790 return result; 785 return result;
791 } 786 }
792 787
793 788
794 ActionNode* ActionNode::PositiveSubmatchSuccess(int stack_reg, 789 ActionNode* ActionNode::PositiveSubmatchSuccess(intptr_t stack_reg,
795 int position_reg, 790 intptr_t position_reg,
796 int clear_register_count, 791 intptr_t clear_register_count,
797 int clear_register_from, 792 intptr_t clear_register_from,
798 RegExpNode* on_success) { 793 RegExpNode* on_success) {
799 ActionNode* result = 794 ActionNode* result =
800 new(on_success->zone()) ActionNode(POSITIVE_SUBMATCH_SUCCESS, on_success); 795 new(on_success->isolate()) ActionNode(POSITIVE_SUBMATCH_SUCCESS,
796 on_success);
801 result->data_.u_submatch.stack_pointer_register = stack_reg; 797 result->data_.u_submatch.stack_pointer_register = stack_reg;
802 result->data_.u_submatch.current_position_register = position_reg; 798 result->data_.u_submatch.current_position_register = position_reg;
803 result->data_.u_submatch.clear_register_count = clear_register_count; 799 result->data_.u_submatch.clear_register_count = clear_register_count;
804 result->data_.u_submatch.clear_register_from = clear_register_from; 800 result->data_.u_submatch.clear_register_from = clear_register_from;
805 return result; 801 return result;
806 } 802 }
807 803
808 804
809 ActionNode* ActionNode::EmptyMatchCheck(int start_register, 805 ActionNode* ActionNode::EmptyMatchCheck(intptr_t start_register,
810 int repetition_register, 806 intptr_t repetition_register,
811 int repetition_limit, 807 intptr_t repetition_limit,
812 RegExpNode* on_success) { 808 RegExpNode* on_success) {
813 ActionNode* result = 809 ActionNode* result =
814 new(on_success->zone()) ActionNode(EMPTY_MATCH_CHECK, on_success); 810 new(on_success->isolate()) ActionNode(EMPTY_MATCH_CHECK, on_success);
815 result->data_.u_empty_match_check.start_register = start_register; 811 result->data_.u_empty_match_check.start_register = start_register;
816 result->data_.u_empty_match_check.repetition_register = repetition_register; 812 result->data_.u_empty_match_check.repetition_register = repetition_register;
817 result->data_.u_empty_match_check.repetition_limit = repetition_limit; 813 result->data_.u_empty_match_check.repetition_limit = repetition_limit;
818 return result; 814 return result;
819 } 815 }
820 816
821 817
822 #define DEFINE_ACCEPT(Type) \ 818 #define DEFINE_ACCEPT(Type) \
823 void Type##Node::Accept(NodeVisitor* visitor) { \ 819 void Type##Node::Accept(NodeVisitor* visitor) { \
824 visitor->Visit##Type(this); \ 820 visitor->Visit##Type(this); \
825 } 821 }
826 FOR_EACH_NODE_TYPE(DEFINE_ACCEPT) 822 FOR_EACH_NODE_TYPE(DEFINE_ACCEPT)
827 #undef DEFINE_ACCEPT 823 #undef DEFINE_ACCEPT
828 824
829 825
830 void LoopChoiceNode::Accept(NodeVisitor* visitor) { 826 void LoopChoiceNode::Accept(NodeVisitor* visitor) {
831 visitor->VisitLoopChoice(this); 827 visitor->VisitLoopChoice(this);
832 } 828 }
833 829
834 830
835 // ------------------------------------------------------------------- 831 // -------------------------------------------------------------------
836 // Emit code. 832 // Emit code.
837 833
838 834
839 void ChoiceNode::GenerateGuard(RegExpMacroAssembler* macro_assembler, 835 void ChoiceNode::GenerateGuard(RegExpMacroAssembler* macro_assembler,
840 Guard* guard, 836 Guard* guard,
841 Trace* trace) { 837 Trace* trace) {
842 switch (guard->op()) { 838 switch (guard->op()) {
843 case Guard::LT: 839 case Guard::LT:
844 DCHECK(!trace->mentions_reg(guard->reg())); 840 ASSERT(!trace->mentions_reg(guard->reg()));
845 macro_assembler->IfRegisterGE(guard->reg(), 841 macro_assembler->IfRegisterGE(guard->reg(),
846 guard->value(), 842 guard->value(),
847 trace->backtrack()); 843 trace->backtrack());
848 break; 844 break;
849 case Guard::GEQ: 845 case Guard::GEQ:
850 DCHECK(!trace->mentions_reg(guard->reg())); 846 ASSERT(!trace->mentions_reg(guard->reg()));
851 macro_assembler->IfRegisterLT(guard->reg(), 847 macro_assembler->IfRegisterLT(guard->reg(),
852 guard->value(), 848 guard->value(),
853 trace->backtrack()); 849 trace->backtrack());
854 break; 850 break;
855 } 851 }
856 } 852 }
857 853
858 854
859 // Returns the number of characters in the equivalence class, omitting those 855 // Returns the number of characters in the equivalence class, omitting those
860 // that cannot occur in the source string because it is ASCII. 856 // that cannot occur in the source string because it is ASCII.
861 static int GetCaseIndependentLetters(Isolate* isolate, uc16 character, 857 static intptr_t GetCaseIndependentLetters(uint16_t character,
862 bool one_byte_subject, 858 bool one_byte_subject,
863 unibrow::uchar* letters) { 859 int32_t* letters) {
864 int length = 860 unibrow::Mapping<unibrow::Ecma262UnCanonicalize> jsregexp_uncanonicalize;
865 isolate->jsregexp_uncanonicalize()->get(character, '\0', letters); 861 intptr_t length = jsregexp_uncanonicalize.get(character, '\0', letters);
866 // Unibrow returns 0 or 1 for characters where case independence is 862 // Unibrow returns 0 or 1 for characters where case independence is
867 // trivial. 863 // trivial.
868 if (length == 0) { 864 if (length == 0) {
869 letters[0] = character; 865 letters[0] = character;
870 length = 1; 866 length = 1;
871 } 867 }
872 if (!one_byte_subject || character <= String::kMaxOneByteCharCode) { 868 if (!one_byte_subject || character <= Symbols::kMaxOneCharCodeSymbol) {
873 return length; 869 return length;
874 } 870 }
875 871
876 // The standard requires that non-ASCII characters cannot have ASCII 872 // The standard requires that non-ASCII characters cannot have ASCII
877 // character codes in their equivalence class. 873 // character codes in their equivalence class.
878 // TODO(dcarney): issue 3550 this is not actually true for Latin1 anymore, 874 // TODO(dcarney): issue 3550 this is not actually true for Latin1 anymore,
879 // is it? For example, \u00C5 is equivalent to \u212B. 875 // is it? For example, \u00C5 is equivalent to \u212B.
880 return 0; 876 return 0;
881 } 877 }
882 878
883 879
884 static inline bool EmitSimpleCharacter(Isolate* isolate, 880 static inline bool EmitSimpleCharacter(Isolate* isolate,
885 RegExpCompiler* compiler, 881 RegExpCompiler* compiler,
886 uc16 c, 882 uint16_t c,
887 Label* on_failure, 883 BlockLabel* on_failure,
888 int cp_offset, 884 intptr_t cp_offset,
889 bool check, 885 bool check,
890 bool preloaded) { 886 bool preloaded) {
891 RegExpMacroAssembler* assembler = compiler->macro_assembler(); 887 RegExpMacroAssembler* assembler = compiler->macro_assembler();
892 bool bound_checked = false; 888 bool bound_checked = false;
893 if (!preloaded) { 889 if (!preloaded) {
894 assembler->LoadCurrentCharacter( 890 assembler->LoadCurrentCharacter(
895 cp_offset, 891 cp_offset,
896 on_failure, 892 on_failure,
897 check); 893 check);
898 bound_checked = true; 894 bound_checked = true;
899 } 895 }
900 assembler->CheckNotCharacter(c, on_failure); 896 assembler->CheckNotCharacter(c, on_failure);
901 return bound_checked; 897 return bound_checked;
902 } 898 }
903 899
904 900
905 // Only emits non-letters (things that don't have case). Only used for case 901 // Only emits non-letters (things that don't have case). Only used for case
906 // independent matches. 902 // independent matches.
907 static inline bool EmitAtomNonLetter(Isolate* isolate, 903 static inline bool EmitAtomNonLetter(Isolate* isolate,
908 RegExpCompiler* compiler, 904 RegExpCompiler* compiler,
909 uc16 c, 905 uint16_t c,
910 Label* on_failure, 906 BlockLabel* on_failure,
911 int cp_offset, 907 intptr_t cp_offset,
912 bool check, 908 bool check,
913 bool preloaded) { 909 bool preloaded) {
914 RegExpMacroAssembler* macro_assembler = compiler->macro_assembler(); 910 RegExpMacroAssembler* macro_assembler = compiler->macro_assembler();
915 bool one_byte = compiler->one_byte(); 911 bool one_byte = compiler->one_byte();
916 unibrow::uchar chars[unibrow::Ecma262UnCanonicalize::kMaxWidth]; 912 int32_t chars[unibrow::Ecma262UnCanonicalize::kMaxWidth];
917 int length = GetCaseIndependentLetters(isolate, c, one_byte, chars); 913 intptr_t length = GetCaseIndependentLetters(c, one_byte, chars);
918 if (length < 1) { 914 if (length < 1) {
919 // This can't match. Must be an one-byte subject and a non-one-byte 915 // This can't match. Must be an one-byte subject and a non-one-byte
920 // character. We do not need to do anything since the one-byte pass 916 // character. We do not need to do anything since the one-byte pass
921 // already handled this. 917 // already handled this.
922 return false; // Bounds not checked. 918 return false; // Bounds not checked.
923 } 919 }
924 bool checked = false; 920 bool checked = false;
925 // We handle the length > 1 case in a later pass. 921 // We handle the length > 1 case in a later pass.
926 if (length == 1) { 922 if (length == 1) {
927 if (one_byte && c > String::kMaxOneByteCharCodeU) { 923 if (one_byte && c > Symbols::kMaxOneCharCodeSymbol) {
928 // Can't match - see above. 924 // Can't match - see above.
929 return false; // Bounds not checked. 925 return false; // Bounds not checked.
930 } 926 }
931 if (!preloaded) { 927 if (!preloaded) {
932 macro_assembler->LoadCurrentCharacter(cp_offset, on_failure, check); 928 macro_assembler->LoadCurrentCharacter(cp_offset, on_failure, check);
933 checked = check; 929 checked = check;
934 } 930 }
935 macro_assembler->CheckNotCharacter(c, on_failure); 931 macro_assembler->CheckNotCharacter(c, on_failure);
936 } 932 }
937 return checked; 933 return checked;
938 } 934 }
939 935
940 936
941 static bool ShortCutEmitCharacterPair(RegExpMacroAssembler* macro_assembler, 937 static bool ShortCutEmitCharacterPair(RegExpMacroAssembler* macro_assembler,
942 bool one_byte, uc16 c1, uc16 c2, 938 bool one_byte,
943 Label* on_failure) { 939 uint16_t c1,
944 uc16 char_mask; 940 uint16_t c2,
941 BlockLabel* on_failure) {
942 uint16_t char_mask;
945 if (one_byte) { 943 if (one_byte) {
946 char_mask = String::kMaxOneByteCharCode; 944 char_mask = Symbols::kMaxOneCharCodeSymbol;
947 } else { 945 } else {
948 char_mask = String::kMaxUtf16CodeUnit; 946 char_mask = Utf16::kMaxCodeUnit;
949 } 947 }
950 uc16 exor = c1 ^ c2; 948 uint16_t exor = c1 ^ c2;
951 // Check whether exor has only one bit set. 949 // Check whether exor has only one bit set.
952 if (((exor - 1) & exor) == 0) { 950 if (((exor - 1) & exor) == 0) {
953 // If c1 and c2 differ only by one bit. 951 // If c1 and c2 differ only by one bit.
954 // Ecma262UnCanonicalize always gives the highest number last. 952 // Ecma262UnCanonicalize always gives the highest number last.
955 DCHECK(c2 > c1); 953 ASSERT(c2 > c1);
956 uc16 mask = char_mask ^ exor; 954 uint16_t mask = char_mask ^ exor;
957 macro_assembler->CheckNotCharacterAfterAnd(c1, mask, on_failure); 955 macro_assembler->CheckNotCharacterAfterAnd(c1, mask, on_failure);
958 return true; 956 return true;
959 } 957 }
960 DCHECK(c2 > c1); 958 ASSERT(c2 > c1);
961 uc16 diff = c2 - c1; 959 uint16_t diff = c2 - c1;
962 if (((diff - 1) & diff) == 0 && c1 >= diff) { 960 if (((diff - 1) & diff) == 0 && c1 >= diff) {
963 // If the characters differ by 2^n but don't differ by one bit then 961 // If the characters differ by 2^n but don't differ by one bit then
964 // subtract the difference from the found character, then do the or 962 // subtract the difference from the found character, then do the or
965 // trick. We avoid the theoretical case where negative numbers are 963 // trick. We avoid the theoretical case where negative numbers are
966 // involved in order to simplify code generation. 964 // involved in order to simplify code generation.
967 uc16 mask = char_mask ^ diff; 965 uint16_t mask = char_mask ^ diff;
968 macro_assembler->CheckNotCharacterAfterMinusAnd(c1 - diff, 966 macro_assembler->CheckNotCharacterAfterMinusAnd(c1 - diff,
969 diff, 967 diff,
970 mask, 968 mask,
971 on_failure); 969 on_failure);
972 return true; 970 return true;
973 } 971 }
974 return false; 972 return false;
975 } 973 }
976 974
977 975
978 typedef bool EmitCharacterFunction(Isolate* isolate, 976 typedef bool EmitCharacterFunction(Isolate* isolate,
979 RegExpCompiler* compiler, 977 RegExpCompiler* compiler,
980 uc16 c, 978 uint16_t c,
981 Label* on_failure, 979 BlockLabel* on_failure,
982 int cp_offset, 980 intptr_t cp_offset,
983 bool check, 981 bool check,
984 bool preloaded); 982 bool preloaded);
985 983
986 // Only emits letters (things that have case). Only used for case independent 984 // Only emits letters (things that have case). Only used for case independent
987 // matches. 985 // matches.
988 static inline bool EmitAtomLetter(Isolate* isolate, 986 static inline bool EmitAtomLetter(Isolate* isolate,
989 RegExpCompiler* compiler, 987 RegExpCompiler* compiler,
990 uc16 c, 988 uint16_t c,
991 Label* on_failure, 989 BlockLabel* on_failure,
992 int cp_offset, 990 intptr_t cp_offset,
993 bool check, 991 bool check,
994 bool preloaded) { 992 bool preloaded) {
995 RegExpMacroAssembler* macro_assembler = compiler->macro_assembler(); 993 RegExpMacroAssembler* macro_assembler = compiler->macro_assembler();
996 bool one_byte = compiler->one_byte(); 994 bool one_byte = compiler->one_byte();
997 unibrow::uchar chars[unibrow::Ecma262UnCanonicalize::kMaxWidth]; 995 int32_t chars[unibrow::Ecma262UnCanonicalize::kMaxWidth];
998 int length = GetCaseIndependentLetters(isolate, c, one_byte, chars); 996 intptr_t length = GetCaseIndependentLetters(c, one_byte, chars);
999 if (length <= 1) return false; 997 if (length <= 1) return false;
1000 // We may not need to check against the end of the input string 998 // We may not need to check against the end of the input string
1001 // if this character lies before a character that matched. 999 // if this character lies before a character that matched.
1002 if (!preloaded) { 1000 if (!preloaded) {
1003 macro_assembler->LoadCurrentCharacter(cp_offset, on_failure, check); 1001 macro_assembler->LoadCurrentCharacter(cp_offset, on_failure, check);
1004 } 1002 }
1005 Label ok; 1003 BlockLabel ok;
1006 DCHECK(unibrow::Ecma262UnCanonicalize::kMaxWidth == 4); 1004 ASSERT(unibrow::Ecma262UnCanonicalize::kMaxWidth == 4);
1007 switch (length) { 1005 switch (length) {
1008 case 2: { 1006 case 2: {
1009 if (ShortCutEmitCharacterPair(macro_assembler, one_byte, chars[0], 1007 if (ShortCutEmitCharacterPair(macro_assembler,
1010 chars[1], on_failure)) { 1008 one_byte,
1009 chars[0],
1010 chars[1],
1011 on_failure)) {
1011 } else { 1012 } else {
1012 macro_assembler->CheckCharacter(chars[0], &ok); 1013 macro_assembler->CheckCharacter(chars[0], &ok);
1013 macro_assembler->CheckNotCharacter(chars[1], on_failure); 1014 macro_assembler->CheckNotCharacter(chars[1], on_failure);
1014 macro_assembler->Bind(&ok); 1015 macro_assembler->BindBlock(&ok);
1015 } 1016 }
1016 break; 1017 break;
1017 } 1018 }
1018 case 4: 1019 case 4:
1019 macro_assembler->CheckCharacter(chars[3], &ok); 1020 macro_assembler->CheckCharacter(chars[3], &ok);
1020 // Fall through! 1021 // Fall through!
1021 case 3: 1022 case 3:
1022 macro_assembler->CheckCharacter(chars[0], &ok); 1023 macro_assembler->CheckCharacter(chars[0], &ok);
1023 macro_assembler->CheckCharacter(chars[1], &ok); 1024 macro_assembler->CheckCharacter(chars[1], &ok);
1024 macro_assembler->CheckNotCharacter(chars[2], on_failure); 1025 macro_assembler->CheckNotCharacter(chars[2], on_failure);
1025 macro_assembler->Bind(&ok); 1026 macro_assembler->BindBlock(&ok);
1026 break; 1027 break;
1027 default: 1028 default:
1028 UNREACHABLE(); 1029 UNREACHABLE();
1029 break; 1030 break;
1030 } 1031 }
1031 return true; 1032 return true;
1032 } 1033 }
1033 1034
1034 1035
1035 static void EmitBoundaryTest(RegExpMacroAssembler* masm, 1036 static void EmitBoundaryTest(RegExpMacroAssembler* masm,
1036 int border, 1037 intptr_t border,
1037 Label* fall_through, 1038 BlockLabel* fall_through,
1038 Label* above_or_equal, 1039 BlockLabel* above_or_equal,
1039 Label* below) { 1040 BlockLabel* below) {
1040 if (below != fall_through) { 1041 if (below != fall_through) {
1041 masm->CheckCharacterLT(border, below); 1042 masm->CheckCharacterLT(border, below);
1042 if (above_or_equal != fall_through) masm->GoTo(above_or_equal); 1043 if (above_or_equal != fall_through) masm->GoTo(above_or_equal);
1043 } else { 1044 } else {
1044 masm->CheckCharacterGT(border - 1, above_or_equal); 1045 masm->CheckCharacterGT(border - 1, above_or_equal);
1045 } 1046 }
1046 } 1047 }
1047 1048
1048 1049
1049 static void EmitDoubleBoundaryTest(RegExpMacroAssembler* masm, 1050 static void EmitDoubleBoundaryTest(RegExpMacroAssembler* masm,
1050 int first, 1051 intptr_t first,
1051 int last, 1052 intptr_t last,
1052 Label* fall_through, 1053 BlockLabel* fall_through,
1053 Label* in_range, 1054 BlockLabel* in_range,
1054 Label* out_of_range) { 1055 BlockLabel* out_of_range) {
1055 if (in_range == fall_through) { 1056 if (in_range == fall_through) {
1056 if (first == last) { 1057 if (first == last) {
1057 masm->CheckNotCharacter(first, out_of_range); 1058 masm->CheckNotCharacter(first, out_of_range);
1058 } else { 1059 } else {
1059 masm->CheckCharacterNotInRange(first, last, out_of_range); 1060 masm->CheckCharacterNotInRange(first, last, out_of_range);
1060 } 1061 }
1061 } else { 1062 } else {
1062 if (first == last) { 1063 if (first == last) {
1063 masm->CheckCharacter(first, in_range); 1064 masm->CheckCharacter(first, in_range);
1064 } else { 1065 } else {
1065 masm->CheckCharacterInRange(first, last, in_range); 1066 masm->CheckCharacterInRange(first, last, in_range);
1066 } 1067 }
1067 if (out_of_range != fall_through) masm->GoTo(out_of_range); 1068 if (out_of_range != fall_through) masm->GoTo(out_of_range);
1068 } 1069 }
1069 } 1070 }
1070 1071
1071 1072
1072 // even_label is for ranges[i] to ranges[i + 1] where i - start_index is even. 1073 // even_label is for ranges[i] to ranges[i + 1] where i - start_index is even.
1073 // odd_label is for ranges[i] to ranges[i + 1] where i - start_index is odd. 1074 // odd_label is for ranges[i] to ranges[i + 1] where i - start_index is odd.
1074 static void EmitUseLookupTable( 1075 static void EmitUseLookupTable(
1075 RegExpMacroAssembler* masm, 1076 RegExpMacroAssembler* masm,
1076 ZoneList<int>* ranges, 1077 ZoneGrowableArray<int>* ranges,
1077 int start_index, 1078 intptr_t start_index,
1078 int end_index, 1079 intptr_t end_index,
1079 int min_char, 1080 intptr_t min_char,
1080 Label* fall_through, 1081 BlockLabel* fall_through,
1081 Label* even_label, 1082 BlockLabel* even_label,
1082 Label* odd_label) { 1083 BlockLabel* odd_label) {
1083 static const int kSize = RegExpMacroAssembler::kTableSize; 1084 static const intptr_t kSize = RegExpMacroAssembler::kTableSize;
1084 static const int kMask = RegExpMacroAssembler::kTableMask; 1085 static const intptr_t kMask = RegExpMacroAssembler::kTableMask;
1085 1086
1086 int base = (min_char & ~kMask); 1087 intptr_t base = (min_char & ~kMask);
1087 USE(base);
1088 1088
1089 // Assert that everything is on one kTableSize page. 1089 // Assert that everything is on one kTableSize page.
1090 for (int i = start_index; i <= end_index; i++) { 1090 for (intptr_t i = start_index; i <= end_index; i++) {
1091 DCHECK_EQ(ranges->at(i) & ~kMask, base); 1091 ASSERT((ranges->At(i) & ~kMask) == base);
1092 } 1092 }
1093 DCHECK(start_index == 0 || (ranges->at(start_index - 1) & ~kMask) <= base); 1093 ASSERT(start_index == 0 || (ranges->At(start_index - 1) & ~kMask) <= base);
1094 1094
1095 char templ[kSize]; 1095 char templ[kSize];
1096 Label* on_bit_set; 1096 BlockLabel* on_bit_set;
1097 Label* on_bit_clear; 1097 BlockLabel* on_bit_clear;
1098 int bit; 1098 intptr_t bit;
1099 if (even_label == fall_through) { 1099 if (even_label == fall_through) {
1100 on_bit_set = odd_label; 1100 on_bit_set = odd_label;
1101 on_bit_clear = even_label; 1101 on_bit_clear = even_label;
1102 bit = 1; 1102 bit = 1;
1103 } else { 1103 } else {
1104 on_bit_set = even_label; 1104 on_bit_set = even_label;
1105 on_bit_clear = odd_label; 1105 on_bit_clear = odd_label;
1106 bit = 0; 1106 bit = 0;
1107 } 1107 }
1108 for (int i = 0; i < (ranges->at(start_index) & kMask) && i < kSize; i++) { 1108 for (intptr_t i = 0; i < (ranges->At(start_index) & kMask) && i < kSize;
1109 i++) {
1109 templ[i] = bit; 1110 templ[i] = bit;
1110 } 1111 }
1111 int j = 0; 1112 intptr_t j = 0;
1112 bit ^= 1; 1113 bit ^= 1;
1113 for (int i = start_index; i < end_index; i++) { 1114 for (intptr_t i = start_index; i < end_index; i++) {
1114 for (j = (ranges->at(i) & kMask); j < (ranges->at(i + 1) & kMask); j++) { 1115 for (j = (ranges->At(i) & kMask); j < (ranges->At(i + 1) & kMask); j++) {
1115 templ[j] = bit; 1116 templ[j] = bit;
1116 } 1117 }
1117 bit ^= 1; 1118 bit ^= 1;
1118 } 1119 }
1119 for (int i = j; i < kSize; i++) { 1120 for (intptr_t i = j; i < kSize; i++) {
1120 templ[i] = bit; 1121 templ[i] = bit;
1121 } 1122 }
1122 Factory* factory = masm->zone()->isolate()->factory();
1123 // TODO(erikcorry): Cache these. 1123 // TODO(erikcorry): Cache these.
1124 Handle<ByteArray> ba = factory->NewByteArray(kSize, TENURED); 1124 const TypedData& ba = TypedData::ZoneHandle(
1125 for (int i = 0; i < kSize; i++) { 1125 masm->isolate(),
1126 ba->set(i, templ[i]); 1126 TypedData::New(kTypedDataUint8ArrayCid, kSize, Heap::kOld));
1127 for (intptr_t i = 0; i < kSize; i++) {
1128 ba.SetUint8(i, templ[i]);
1127 } 1129 }
1128 masm->CheckBitInTable(ba, on_bit_set); 1130 masm->CheckBitInTable(ba, on_bit_set);
1129 if (on_bit_clear != fall_through) masm->GoTo(on_bit_clear); 1131 if (on_bit_clear != fall_through) masm->GoTo(on_bit_clear);
1130 } 1132 }
1131 1133
1132 1134
1133 static void CutOutRange(RegExpMacroAssembler* masm, 1135 static void CutOutRange(RegExpMacroAssembler* masm,
1134 ZoneList<int>* ranges, 1136 ZoneGrowableArray<int>* ranges,
1135 int start_index, 1137 intptr_t start_index,
1136 int end_index, 1138 intptr_t end_index,
1137 int cut_index, 1139 intptr_t cut_index,
1138 Label* even_label, 1140 BlockLabel* even_label,
1139 Label* odd_label) { 1141 BlockLabel* odd_label) {
1140 bool odd = (((cut_index - start_index) & 1) == 1); 1142 bool odd = (((cut_index - start_index) & 1) == 1);
1141 Label* in_range_label = odd ? odd_label : even_label; 1143 BlockLabel* in_range_label = odd ? odd_label : even_label;
1142 Label dummy; 1144 BlockLabel dummy;
1143 EmitDoubleBoundaryTest(masm, 1145 EmitDoubleBoundaryTest(masm,
1144 ranges->at(cut_index), 1146 ranges->At(cut_index),
1145 ranges->at(cut_index + 1) - 1, 1147 ranges->At(cut_index + 1) - 1,
1146 &dummy, 1148 &dummy,
1147 in_range_label, 1149 in_range_label,
1148 &dummy); 1150 &dummy);
1149 DCHECK(!dummy.is_linked()); 1151 ASSERT(!dummy.IsLinked());
1150 // Cut out the single range by rewriting the array. This creates a new 1152 // Cut out the single range by rewriting the array. This creates a new
1151 // range that is a merger of the two ranges on either side of the one we 1153 // range that is a merger of the two ranges on either side of the one we
1152 // are cutting out. The oddity of the labels is preserved. 1154 // are cutting out. The oddity of the labels is preserved.
1153 for (int j = cut_index; j > start_index; j--) { 1155 for (intptr_t j = cut_index; j > start_index; j--) {
1154 ranges->at(j) = ranges->at(j - 1); 1156 (*ranges)[j] = ranges->At(j - 1);
1155 } 1157 }
1156 for (int j = cut_index + 1; j < end_index; j++) { 1158 for (intptr_t j = cut_index + 1; j < end_index; j++) {
1157 ranges->at(j) = ranges->at(j + 1); 1159 (*ranges)[j] = ranges->At(j + 1);
1158 } 1160 }
1159 } 1161 }
1160 1162
1161 1163
1162 // Unicode case. Split the search space into kSize spaces that are handled 1164 // Unicode case. Split the search space into kSize spaces that are handled
1163 // with recursion. 1165 // with recursion.
1164 static void SplitSearchSpace(ZoneList<int>* ranges, 1166 static void SplitSearchSpace(ZoneGrowableArray<int>* ranges,
1165 int start_index, 1167 intptr_t start_index,
1166 int end_index, 1168 intptr_t end_index,
1167 int* new_start_index, 1169 intptr_t* new_start_index,
1168 int* new_end_index, 1170 intptr_t* new_end_index,
1169 int* border) { 1171 intptr_t* border) {
1170 static const int kSize = RegExpMacroAssembler::kTableSize; 1172 static const intptr_t kSize = RegExpMacroAssembler::kTableSize;
1171 static const int kMask = RegExpMacroAssembler::kTableMask; 1173 static const intptr_t kMask = RegExpMacroAssembler::kTableMask;
1172 1174
1173 int first = ranges->at(start_index); 1175 intptr_t first = ranges->At(start_index);
1174 int last = ranges->at(end_index) - 1; 1176 intptr_t last = ranges->At(end_index) - 1;
1175 1177
1176 *new_start_index = start_index; 1178 *new_start_index = start_index;
1177 *border = (ranges->at(start_index) & ~kMask) + kSize; 1179 *border = (ranges->At(start_index) & ~kMask) + kSize;
1178 while (*new_start_index < end_index) { 1180 while (*new_start_index < end_index) {
1179 if (ranges->at(*new_start_index) > *border) break; 1181 if (ranges->At(*new_start_index) > *border) break;
1180 (*new_start_index)++; 1182 (*new_start_index)++;
1181 } 1183 }
1182 // new_start_index is the index of the first edge that is beyond the 1184 // new_start_index is the index of the first edge that is beyond the
1183 // current kSize space. 1185 // current kSize space.
1184 1186
1185 // For very large search spaces we do a binary chop search of the non-Latin1 1187 // For very large search spaces we do a binary chop search of the non-Latin1
1186 // space instead of just going to the end of the current kSize space. The 1188 // space instead of just going to the end of the current kSize space. The
1187 // heuristics are complicated a little by the fact that any 128-character 1189 // heuristics are complicated a little by the fact that any 128-character
1188 // encoding space can be quickly tested with a table lookup, so we don't 1190 // encoding space can be quickly tested with a table lookup, so we don't
1189 // wish to do binary chop search at a smaller granularity than that. A 1191 // wish to do binary chop search at a smaller granularity than that. A
1190 // 128-character space can take up a lot of space in the ranges array if, 1192 // 128-character space can take up a lot of space in the ranges array if,
1191 // for example, we only want to match every second character (eg. the lower 1193 // for example, we only want to match every second character (eg. the lower
1192 // case characters on some Unicode pages). 1194 // case characters on some Unicode pages).
1193 int binary_chop_index = (end_index + start_index) / 2; 1195 intptr_t binary_chop_index = (end_index + start_index) / 2;
1194 // The first test ensures that we get to the code that handles the Latin1 1196 // The first test ensures that we get to the code that handles the Latin1
1195 // range with a single not-taken branch, speeding up this important 1197 // range with a single not-taken branch, speeding up this important
1196 // character range (even non-Latin1 charset-based text has spaces and 1198 // character range (even non-Latin1 charset-based text has spaces and
1197 // punctuation). 1199 // punctuation).
1198 if (*border - 1 > String::kMaxOneByteCharCode && // Latin1 case. 1200 if (*border - 1 > Symbols::kMaxOneCharCodeSymbol && // Latin1 case.
1199 end_index - start_index > (*new_start_index - start_index) * 2 && 1201 end_index - start_index > (*new_start_index - start_index) * 2 &&
1200 last - first > kSize * 2 && binary_chop_index > *new_start_index && 1202 last - first > kSize * 2 &&
1201 ranges->at(binary_chop_index) >= first + 2 * kSize) { 1203 binary_chop_index > *new_start_index &&
1202 int scan_forward_for_section_border = binary_chop_index;; 1204 ranges->At(binary_chop_index) >= first + 2 * kSize) {
1203 int new_border = (ranges->at(binary_chop_index) | kMask) + 1; 1205 intptr_t scan_forward_for_section_border = binary_chop_index;;
1206 intptr_t new_border = (ranges->At(binary_chop_index) | kMask) + 1;
1204 1207
1205 while (scan_forward_for_section_border < end_index) { 1208 while (scan_forward_for_section_border < end_index) {
1206 if (ranges->at(scan_forward_for_section_border) > new_border) { 1209 if (ranges->At(scan_forward_for_section_border) > new_border) {
1207 *new_start_index = scan_forward_for_section_border; 1210 *new_start_index = scan_forward_for_section_border;
1208 *border = new_border; 1211 *border = new_border;
1209 break; 1212 break;
1210 } 1213 }
1211 scan_forward_for_section_border++; 1214 scan_forward_for_section_border++;
1212 } 1215 }
1213 } 1216 }
1214 1217
1215 DCHECK(*new_start_index > start_index); 1218 ASSERT(*new_start_index > start_index);
1216 *new_end_index = *new_start_index - 1; 1219 *new_end_index = *new_start_index - 1;
1217 if (ranges->at(*new_end_index) == *border) { 1220 if (ranges->At(*new_end_index) == *border) {
1218 (*new_end_index)--; 1221 (*new_end_index)--;
1219 } 1222 }
1220 if (*border >= ranges->at(end_index)) { 1223 if (*border >= ranges->At(end_index)) {
1221 *border = ranges->at(end_index); 1224 *border = ranges->At(end_index);
1222 *new_start_index = end_index; // Won't be used. 1225 *new_start_index = end_index; // Won't be used.
1223 *new_end_index = end_index - 1; 1226 *new_end_index = end_index - 1;
1224 } 1227 }
1225 } 1228 }
1226 1229
1227 1230
1228 // Gets a series of segment boundaries representing a character class. If the 1231 // Gets a series of segment boundaries representing a character class. If the
1229 // character is in the range between an even and an odd boundary (counting from 1232 // character is in the range between an even and an odd boundary (counting from
1230 // start_index) then go to even_label, otherwise go to odd_label. We already 1233 // start_index) then go to even_label, otherwise go to odd_label. We already
1231 // know that the character is in the range of min_char to max_char inclusive. 1234 // know that the character is in the range of min_char to max_char inclusive.
1232 // Either label can be NULL indicating backtracking. Either label can also be 1235 // Either label can be NULL indicating backtracking. Either label can also be
1233 // equal to the fall_through label. 1236 // equal to the fall_through label.
1234 static void GenerateBranches(RegExpMacroAssembler* masm, 1237 static void GenerateBranches(RegExpMacroAssembler* masm,
1235 ZoneList<int>* ranges, 1238 ZoneGrowableArray<int>* ranges,
1236 int start_index, 1239 intptr_t start_index,
1237 int end_index, 1240 intptr_t end_index,
1238 uc16 min_char, 1241 uint16_t min_char,
1239 uc16 max_char, 1242 uint16_t max_char,
1240 Label* fall_through, 1243 BlockLabel* fall_through,
1241 Label* even_label, 1244 BlockLabel* even_label,
1242 Label* odd_label) { 1245 BlockLabel* odd_label) {
1243 int first = ranges->at(start_index); 1246 intptr_t first = ranges->At(start_index);
1244 int last = ranges->at(end_index) - 1; 1247 intptr_t last = ranges->At(end_index) - 1;
1245 1248
1246 DCHECK_LT(min_char, first); 1249 ASSERT(min_char < first);
1247 1250
1248 // Just need to test if the character is before or on-or-after 1251 // Just need to test if the character is before or on-or-after
1249 // a particular character. 1252 // a particular character.
1250 if (start_index == end_index) { 1253 if (start_index == end_index) {
1251 EmitBoundaryTest(masm, first, fall_through, even_label, odd_label); 1254 EmitBoundaryTest(masm, first, fall_through, even_label, odd_label);
1252 return; 1255 return;
1253 } 1256 }
1254 1257
1255 // Another almost trivial case: There is one interval in the middle that is 1258 // Another almost trivial case: There is one interval in the middle that is
1256 // different from the end intervals. 1259 // different from the end intervals.
1257 if (start_index + 1 == end_index) { 1260 if (start_index + 1 == end_index) {
1258 EmitDoubleBoundaryTest( 1261 EmitDoubleBoundaryTest(
1259 masm, first, last, fall_through, even_label, odd_label); 1262 masm, first, last, fall_through, even_label, odd_label);
1260 return; 1263 return;
1261 } 1264 }
1262 1265
1263 // It's not worth using table lookup if there are very few intervals in the 1266 // It's not worth using table lookup if there are very few intervals in the
1264 // character class. 1267 // character class.
1265 if (end_index - start_index <= 6) { 1268 if (end_index - start_index <= 6) {
1266 // It is faster to test for individual characters, so we look for those 1269 // It is faster to test for individual characters, so we look for those
1267 // first, then try arbitrary ranges in the second round. 1270 // first, then try arbitrary ranges in the second round.
1268 static int kNoCutIndex = -1; 1271 static intptr_t kNoCutIndex = -1;
1269 int cut = kNoCutIndex; 1272 intptr_t cut = kNoCutIndex;
1270 for (int i = start_index; i < end_index; i++) { 1273 for (intptr_t i = start_index; i < end_index; i++) {
1271 if (ranges->at(i) == ranges->at(i + 1) - 1) { 1274 if (ranges->At(i) == ranges->At(i + 1) - 1) {
1272 cut = i; 1275 cut = i;
1273 break; 1276 break;
1274 } 1277 }
1275 } 1278 }
1276 if (cut == kNoCutIndex) cut = start_index; 1279 if (cut == kNoCutIndex) cut = start_index;
1277 CutOutRange( 1280 CutOutRange(
1278 masm, ranges, start_index, end_index, cut, even_label, odd_label); 1281 masm, ranges, start_index, end_index, cut, even_label, odd_label);
1279 DCHECK_GE(end_index - start_index, 2); 1282 ASSERT(end_index - start_index >= 2);
1280 GenerateBranches(masm, 1283 GenerateBranches(masm,
1281 ranges, 1284 ranges,
1282 start_index + 1, 1285 start_index + 1,
1283 end_index - 1, 1286 end_index - 1,
1284 min_char, 1287 min_char,
1285 max_char, 1288 max_char,
1286 fall_through, 1289 fall_through,
1287 even_label, 1290 even_label,
1288 odd_label); 1291 odd_label);
1289 return; 1292 return;
1290 } 1293 }
1291 1294
1292 // If there are a lot of intervals in the regexp, then we will use tables to 1295 // If there are a lot of intervals in the regexp, then we will use tables to
1293 // determine whether the character is inside or outside the character class. 1296 // determine whether the character is inside or outside the character class.
1294 static const int kBits = RegExpMacroAssembler::kTableSizeBits; 1297 static const intptr_t kBits = RegExpMacroAssembler::kTableSizeBits;
1295 1298
1296 if ((max_char >> kBits) == (min_char >> kBits)) { 1299 if ((max_char >> kBits) == (min_char >> kBits)) {
1297 EmitUseLookupTable(masm, 1300 EmitUseLookupTable(masm,
1298 ranges, 1301 ranges,
1299 start_index, 1302 start_index,
1300 end_index, 1303 end_index,
1301 min_char, 1304 min_char,
1302 fall_through, 1305 fall_through,
1303 even_label, 1306 even_label,
1304 odd_label); 1307 odd_label);
1305 return; 1308 return;
1306 } 1309 }
1307 1310
1308 if ((min_char >> kBits) != (first >> kBits)) { 1311 if ((min_char >> kBits) != (first >> kBits)) {
1309 masm->CheckCharacterLT(first, odd_label); 1312 masm->CheckCharacterLT(first, odd_label);
1310 GenerateBranches(masm, 1313 GenerateBranches(masm,
1311 ranges, 1314 ranges,
1312 start_index + 1, 1315 start_index + 1,
1313 end_index, 1316 end_index,
1314 first, 1317 first,
1315 max_char, 1318 max_char,
1316 fall_through, 1319 fall_through,
1317 odd_label, 1320 odd_label,
1318 even_label); 1321 even_label);
1319 return; 1322 return;
1320 } 1323 }
1321 1324
1322 int new_start_index = 0; 1325 intptr_t new_start_index = 0;
1323 int new_end_index = 0; 1326 intptr_t new_end_index = 0;
1324 int border = 0; 1327 intptr_t border = 0;
1325 1328
1326 SplitSearchSpace(ranges, 1329 SplitSearchSpace(ranges,
1327 start_index, 1330 start_index,
1328 end_index, 1331 end_index,
1329 &new_start_index, 1332 &new_start_index,
1330 &new_end_index, 1333 &new_end_index,
1331 &border); 1334 &border);
1332 1335
1333 Label handle_rest; 1336 BlockLabel handle_rest;
1334 Label* above = &handle_rest; 1337 BlockLabel* above = &handle_rest;
1335 if (border == last + 1) { 1338 if (border == last + 1) {
1336 // We didn't find any section that started after the limit, so everything 1339 // We didn't find any section that started after the limit, so everything
1337 // above the border is one of the terminal labels. 1340 // above the border is one of the terminal labels.
1338 above = (end_index & 1) != (start_index & 1) ? odd_label : even_label; 1341 above = (end_index & 1) != (start_index & 1) ? odd_label : even_label;
1339 DCHECK(new_end_index == end_index - 1); 1342 ASSERT(new_end_index == end_index - 1);
1340 } 1343 }
1341 1344
1342 DCHECK_LE(start_index, new_end_index); 1345 ASSERT(start_index <= new_end_index);
1343 DCHECK_LE(new_start_index, end_index); 1346 ASSERT(new_start_index <= end_index);
1344 DCHECK_LT(start_index, new_start_index); 1347 ASSERT(start_index < new_start_index);
1345 DCHECK_LT(new_end_index, end_index); 1348 ASSERT(new_end_index < end_index);
1346 DCHECK(new_end_index + 1 == new_start_index || 1349 ASSERT(new_end_index + 1 == new_start_index ||
1347 (new_end_index + 2 == new_start_index && 1350 (new_end_index + 2 == new_start_index &&
1348 border == ranges->at(new_end_index + 1))); 1351 border == ranges->At(new_end_index + 1)));
1349 DCHECK_LT(min_char, border - 1); 1352 ASSERT(min_char < border - 1);
1350 DCHECK_LT(border, max_char); 1353 ASSERT(border < max_char);
1351 DCHECK_LT(ranges->at(new_end_index), border); 1354 ASSERT(ranges->At(new_end_index) < border);
1352 DCHECK(border < ranges->at(new_start_index) || 1355 ASSERT(border < ranges->At(new_start_index) ||
1353 (border == ranges->at(new_start_index) && 1356 (border == ranges->At(new_start_index) &&
1354 new_start_index == end_index && 1357 new_start_index == end_index &&
1355 new_end_index == end_index - 1 && 1358 new_end_index == end_index - 1 &&
1356 border == last + 1)); 1359 border == last + 1));
1357 DCHECK(new_start_index == 0 || border >= ranges->at(new_start_index - 1)); 1360 ASSERT(new_start_index == 0 || border >= ranges->At(new_start_index - 1));
1358 1361
1359 masm->CheckCharacterGT(border - 1, above); 1362 masm->CheckCharacterGT(border - 1, above);
1360 Label dummy; 1363 BlockLabel dummy;
1361 GenerateBranches(masm, 1364 GenerateBranches(masm,
1362 ranges, 1365 ranges,
1363 start_index, 1366 start_index,
1364 new_end_index, 1367 new_end_index,
1365 min_char, 1368 min_char,
1366 border - 1, 1369 border - 1,
1367 &dummy, 1370 &dummy,
1368 even_label, 1371 even_label,
1369 odd_label); 1372 odd_label);
1370 if (handle_rest.is_linked()) { 1373
1371 masm->Bind(&handle_rest); 1374 if (handle_rest.IsLinked()) {
1375 masm->BindBlock(&handle_rest);
1372 bool flip = (new_start_index & 1) != (start_index & 1); 1376 bool flip = (new_start_index & 1) != (start_index & 1);
1373 GenerateBranches(masm, 1377 GenerateBranches(masm,
1374 ranges, 1378 ranges,
1375 new_start_index, 1379 new_start_index,
1376 end_index, 1380 end_index,
1377 border, 1381 border,
1378 max_char, 1382 max_char,
1379 &dummy, 1383 &dummy,
1380 flip ? odd_label : even_label, 1384 flip ? odd_label : even_label,
1381 flip ? even_label : odd_label); 1385 flip ? even_label : odd_label);
1382 } 1386 }
1383 } 1387 }
1384 1388
1385 1389
1386 static void EmitCharClass(RegExpMacroAssembler* macro_assembler, 1390 static void EmitCharClass(RegExpMacroAssembler* macro_assembler,
1387 RegExpCharacterClass* cc, bool one_byte, 1391 RegExpCharacterClass* cc,
1388 Label* on_failure, int cp_offset, bool check_offset, 1392 bool one_byte,
1389 bool preloaded, Zone* zone) { 1393 BlockLabel* on_failure,
1390 ZoneList<CharacterRange>* ranges = cc->ranges(zone); 1394 intptr_t cp_offset,
1395 bool check_offset,
1396 bool preloaded,
1397 Isolate* isolate) {
1398 ZoneGrowableArray<CharacterRange>* ranges = cc->ranges();
1391 if (!CharacterRange::IsCanonical(ranges)) { 1399 if (!CharacterRange::IsCanonical(ranges)) {
1392 CharacterRange::Canonicalize(ranges); 1400 CharacterRange::Canonicalize(ranges);
1393 } 1401 }
1394 1402
1395 int max_char; 1403 intptr_t max_char;
1396 if (one_byte) { 1404 if (one_byte) {
1397 max_char = String::kMaxOneByteCharCode; 1405 max_char = Symbols::kMaxOneCharCodeSymbol;
1398 } else { 1406 } else {
1399 max_char = String::kMaxUtf16CodeUnit; 1407 max_char = Utf16::kMaxCodeUnit;
1400 } 1408 }
1401 1409
1402 int range_count = ranges->length(); 1410 intptr_t range_count = ranges->length();
1403 1411
1404 int last_valid_range = range_count - 1; 1412 intptr_t last_valid_range = range_count - 1;
1405 while (last_valid_range >= 0) { 1413 while (last_valid_range >= 0) {
1406 CharacterRange& range = ranges->at(last_valid_range); 1414 CharacterRange& range = (*ranges)[last_valid_range];
1407 if (range.from() <= max_char) { 1415 if (range.from() <= max_char) {
1408 break; 1416 break;
1409 } 1417 }
1410 last_valid_range--; 1418 last_valid_range--;
1411 } 1419 }
1412 1420
1413 if (last_valid_range < 0) { 1421 if (last_valid_range < 0) {
1414 if (!cc->is_negated()) { 1422 if (!cc->is_negated()) {
1415 macro_assembler->GoTo(on_failure); 1423 macro_assembler->GoTo(on_failure);
1416 } 1424 }
1417 if (check_offset) { 1425 if (check_offset) {
1418 macro_assembler->CheckPosition(cp_offset, on_failure); 1426 macro_assembler->CheckPosition(cp_offset, on_failure);
1419 } 1427 }
1420 return; 1428 return;
1421 } 1429 }
1422 1430
1423 if (last_valid_range == 0 && 1431 if (last_valid_range == 0 &&
1424 ranges->at(0).IsEverything(max_char)) { 1432 ranges->At(0).IsEverything(max_char)) {
1425 if (cc->is_negated()) { 1433 if (cc->is_negated()) {
1426 macro_assembler->GoTo(on_failure); 1434 macro_assembler->GoTo(on_failure);
1427 } else { 1435 } else {
1428 // This is a common case hit by non-anchored expressions. 1436 // This is a common case hit by non-anchored expressions.
1429 if (check_offset) { 1437 if (check_offset) {
1430 macro_assembler->CheckPosition(cp_offset, on_failure); 1438 macro_assembler->CheckPosition(cp_offset, on_failure);
1431 } 1439 }
1432 } 1440 }
1433 return; 1441 return;
1434 } 1442 }
1435 if (last_valid_range == 0 && 1443 if (last_valid_range == 0 &&
1436 !cc->is_negated() && 1444 !cc->is_negated() &&
1437 ranges->at(0).IsEverything(max_char)) { 1445 ranges->At(0).IsEverything(max_char)) {
1438 // This is a common case hit by non-anchored expressions. 1446 // This is a common case hit by non-anchored expressions.
1439 if (check_offset) { 1447 if (check_offset) {
1440 macro_assembler->CheckPosition(cp_offset, on_failure); 1448 macro_assembler->CheckPosition(cp_offset, on_failure);
1441 } 1449 }
1442 return; 1450 return;
1443 } 1451 }
1444 1452
1445 if (!preloaded) { 1453 if (!preloaded) {
1446 macro_assembler->LoadCurrentCharacter(cp_offset, on_failure, check_offset); 1454 macro_assembler->LoadCurrentCharacter(cp_offset, on_failure, check_offset);
1447 } 1455 }
1448 1456
1449 if (cc->is_standard(zone) && 1457 if (cc->is_standard() &&
1450 macro_assembler->CheckSpecialCharacterClass(cc->standard_type(), 1458 macro_assembler->CheckSpecialCharacterClass(cc->standard_type(),
1451 on_failure)) { 1459 on_failure)) {
1452 return; 1460 return;
1453 } 1461 }
1454 1462
1455 1463
1456 // A new list with ascending entries. Each entry is a code unit 1464 // A new list with ascending entries. Each entry is a code unit
1457 // where there is a boundary between code units that are part of 1465 // where there is a boundary between code units that are part of
1458 // the class and code units that are not. Normally we insert an 1466 // the class and code units that are not. Normally we insert an
1459 // entry at zero which goes to the failure label, but if there 1467 // entry at zero which goes to the failure label, but if there
1460 // was already one there we fall through for success on that entry. 1468 // was already one there we fall through for success on that entry.
1461 // Subsequent entries have alternating meaning (success/failure). 1469 // Subsequent entries have alternating meaning (success/failure).
1462 ZoneList<int>* range_boundaries = 1470 ZoneGrowableArray<int>* range_boundaries =
1463 new(zone) ZoneList<int>(last_valid_range, zone); 1471 new(isolate) ZoneGrowableArray<int>(last_valid_range);
1464 1472
1465 bool zeroth_entry_is_failure = !cc->is_negated(); 1473 bool zeroth_entry_is_failure = !cc->is_negated();
1466 1474
1467 for (int i = 0; i <= last_valid_range; i++) { 1475 for (intptr_t i = 0; i <= last_valid_range; i++) {
1468 CharacterRange& range = ranges->at(i); 1476 CharacterRange& range = (*ranges)[i];
1469 if (range.from() == 0) { 1477 if (range.from() == 0) {
1470 DCHECK_EQ(i, 0); 1478 ASSERT(i == 0);
1471 zeroth_entry_is_failure = !zeroth_entry_is_failure; 1479 zeroth_entry_is_failure = !zeroth_entry_is_failure;
1472 } else { 1480 } else {
1473 range_boundaries->Add(range.from(), zone); 1481 range_boundaries->Add(range.from());
1474 } 1482 }
1475 range_boundaries->Add(range.to() + 1, zone); 1483 range_boundaries->Add(range.to() + 1);
1476 } 1484 }
1477 int end_index = range_boundaries->length() - 1; 1485 intptr_t end_index = range_boundaries->length() - 1;
1478 if (range_boundaries->at(end_index) > max_char) { 1486 if (range_boundaries->At(end_index) > max_char) {
1479 end_index--; 1487 end_index--;
1480 } 1488 }
1481 1489
1482 Label fall_through; 1490 BlockLabel fall_through;
1483 GenerateBranches(macro_assembler, 1491 GenerateBranches(macro_assembler,
1484 range_boundaries, 1492 range_boundaries,
1485 0, // start_index. 1493 0, // start_index.
1486 end_index, 1494 end_index,
1487 0, // min_char. 1495 0, // min_char.
1488 max_char, 1496 max_char,
1489 &fall_through, 1497 &fall_through,
1490 zeroth_entry_is_failure ? &fall_through : on_failure, 1498 zeroth_entry_is_failure ? &fall_through : on_failure,
1491 zeroth_entry_is_failure ? on_failure : &fall_through); 1499 zeroth_entry_is_failure ? on_failure : &fall_through);
1492 macro_assembler->Bind(&fall_through); 1500 macro_assembler->BindBlock(&fall_through);
1493 } 1501 }
1494 1502
1495 1503
1496 RegExpNode::~RegExpNode() { 1504 RegExpNode::~RegExpNode() {
1497 } 1505 }
1498 1506
1499 1507
1500 RegExpNode::LimitResult RegExpNode::LimitVersions(RegExpCompiler* compiler, 1508 RegExpNode::LimitResult RegExpNode::LimitVersions(RegExpCompiler* compiler,
1501 Trace* trace) { 1509 Trace* trace) {
1502 // If we are generating a greedy loop then don't stop and don't reuse code. 1510 // If we are generating a greedy loop then don't stop and don't reuse code.
1503 if (trace->stop_node() != NULL) { 1511 if (trace->stop_node() != NULL) {
1504 return CONTINUE; 1512 return CONTINUE;
1505 } 1513 }
1506 1514
1507 RegExpMacroAssembler* macro_assembler = compiler->macro_assembler(); 1515 RegExpMacroAssembler* macro_assembler = compiler->macro_assembler();
1508 if (trace->is_trivial()) { 1516 if (trace->is_trivial()) {
1509 if (label_.is_bound()) { 1517 if (label_.IsBound()) {
1510 // We are being asked to generate a generic version, but that's already 1518 // We are being asked to generate a generic version, but that's already
1511 // been done so just go to it. 1519 // been done so just go to it.
1512 macro_assembler->GoTo(&label_); 1520 macro_assembler->GoTo(&label_);
1513 return DONE; 1521 return DONE;
1514 } 1522 }
1515 if (compiler->recursion_depth() >= RegExpCompiler::kMaxRecursion) { 1523 if (compiler->recursion_depth() >= RegExpCompiler::kMaxRecursion) {
1516 // To avoid too deep recursion we push the node to the work queue and just 1524 // To avoid too deep recursion we push the node to the work queue and just
1517 // generate a goto here. 1525 // generate a goto here.
1518 compiler->AddWork(this); 1526 compiler->AddWork(this);
1519 macro_assembler->GoTo(&label_); 1527 macro_assembler->GoTo(&label_);
1520 return DONE; 1528 return DONE;
1521 } 1529 }
1522 // Generate generic version of the node and bind the label for later use. 1530 // Generate generic version of the node and bind the label for later use.
1523 macro_assembler->Bind(&label_); 1531 macro_assembler->BindBlock(&label_);
1524 return CONTINUE; 1532 return CONTINUE;
1525 } 1533 }
1526 1534
1527 // We are being asked to make a non-generic version. Keep track of how many 1535 // We are being asked to make a non-generic version. Keep track of how many
1528 // non-generic versions we generate so as not to overdo it. 1536 // non-generic versions we generate so as not to overdo it.
1529 trace_count_++; 1537 trace_count_++;
1530 if (FLAG_regexp_optimization && 1538 if (kRegexpOptimization &&
1531 trace_count_ < kMaxCopiesCodeGenerated && 1539 trace_count_ < kMaxCopiesCodeGenerated &&
1532 compiler->recursion_depth() <= RegExpCompiler::kMaxRecursion) { 1540 compiler->recursion_depth() <= RegExpCompiler::kMaxRecursion) {
1533 return CONTINUE; 1541 return CONTINUE;
1534 } 1542 }
1535 1543
1536 // If we get here code has been generated for this node too many times or 1544 // If we get here code has been generated for this node too many times or
1537 // recursion is too deep. Time to switch to a generic version. The code for 1545 // recursion is too deep. Time to switch to a generic version. The code for
1538 // generic versions above can handle deep recursion properly. 1546 // generic versions above can handle deep recursion properly.
1539 trace->Flush(compiler, this); 1547 trace->Flush(compiler, this);
1540 return DONE; 1548 return DONE;
1541 } 1549 }
1542 1550
1543 1551
1544 int ActionNode::EatsAtLeast(int still_to_find, 1552 intptr_t ActionNode::EatsAtLeast(intptr_t still_to_find,
1545 int budget, 1553 intptr_t budget,
1546 bool not_at_start) { 1554 bool not_at_start) {
1547 if (budget <= 0) return 0; 1555 if (budget <= 0) return 0;
1548 if (action_type_ == POSITIVE_SUBMATCH_SUCCESS) return 0; // Rewinds input! 1556 if (action_type_ == POSITIVE_SUBMATCH_SUCCESS) return 0; // Rewinds input!
1549 return on_success()->EatsAtLeast(still_to_find, 1557 return on_success()->EatsAtLeast(still_to_find,
1550 budget - 1, 1558 budget - 1,
1551 not_at_start); 1559 not_at_start);
1552 } 1560 }
1553 1561
1554 1562
1555 void ActionNode::FillInBMInfo(int offset, 1563 void ActionNode::FillInBMInfo(intptr_t offset,
1556 int budget, 1564 intptr_t budget,
1557 BoyerMooreLookahead* bm, 1565 BoyerMooreLookahead* bm,
1558 bool not_at_start) { 1566 bool not_at_start) {
1559 if (action_type_ == BEGIN_SUBMATCH) { 1567 if (action_type_ == BEGIN_SUBMATCH) {
1560 bm->SetRest(offset); 1568 bm->SetRest(offset);
1561 } else if (action_type_ != POSITIVE_SUBMATCH_SUCCESS) { 1569 } else if (action_type_ != POSITIVE_SUBMATCH_SUCCESS) {
1562 on_success()->FillInBMInfo(offset, budget - 1, bm, not_at_start); 1570 on_success()->FillInBMInfo(offset, budget - 1, bm, not_at_start);
1563 } 1571 }
1564 SaveBMInfo(bm, not_at_start, offset); 1572 SaveBMInfo(bm, not_at_start, offset);
1565 } 1573 }
1566 1574
1567 1575
1568 int AssertionNode::EatsAtLeast(int still_to_find, 1576 intptr_t AssertionNode::EatsAtLeast(intptr_t still_to_find,
1569 int budget, 1577 intptr_t budget,
1570 bool not_at_start) { 1578 bool not_at_start) {
1571 if (budget <= 0) return 0; 1579 if (budget <= 0) return 0;
1572 // If we know we are not at the start and we are asked "how many characters 1580 // If we know we are not at the start and we are asked "how many characters
1573 // will you match if you succeed?" then we can answer anything since false 1581 // will you match if you succeed?" then we can answer anything since false
1574 // implies false. So lets just return the max answer (still_to_find) since 1582 // implies false. So lets just return the max answer (still_to_find) since
1575 // that won't prevent us from preloading a lot of characters for the other 1583 // that won't prevent us from preloading a lot of characters for the other
1576 // branches in the node graph. 1584 // branches in the node graph.
1577 if (assertion_type() == AT_START && not_at_start) return still_to_find; 1585 if (assertion_type() == AT_START && not_at_start) return still_to_find;
1578 return on_success()->EatsAtLeast(still_to_find, 1586 return on_success()->EatsAtLeast(still_to_find,
1579 budget - 1, 1587 budget - 1,
1580 not_at_start); 1588 not_at_start);
1581 } 1589 }
1582 1590
1583 1591
1584 void AssertionNode::FillInBMInfo(int offset, 1592 void AssertionNode::FillInBMInfo(intptr_t offset,
1585 int budget, 1593 intptr_t budget,
1586 BoyerMooreLookahead* bm, 1594 BoyerMooreLookahead* bm,
1587 bool not_at_start) { 1595 bool not_at_start) {
1588 // Match the behaviour of EatsAtLeast on this node. 1596 // Match the behaviour of EatsAtLeast on this node.
1589 if (assertion_type() == AT_START && not_at_start) return; 1597 if (assertion_type() == AT_START && not_at_start) return;
1590 on_success()->FillInBMInfo(offset, budget - 1, bm, not_at_start); 1598 on_success()->FillInBMInfo(offset, budget - 1, bm, not_at_start);
1591 SaveBMInfo(bm, not_at_start, offset); 1599 SaveBMInfo(bm, not_at_start, offset);
1592 } 1600 }
1593 1601
1594 1602
1595 int BackReferenceNode::EatsAtLeast(int still_to_find, 1603 intptr_t BackReferenceNode::EatsAtLeast(intptr_t still_to_find,
1596 int budget, 1604 intptr_t budget,
1597 bool not_at_start) { 1605 bool not_at_start) {
1598 if (budget <= 0) return 0; 1606 if (budget <= 0) return 0;
1599 return on_success()->EatsAtLeast(still_to_find, 1607 return on_success()->EatsAtLeast(still_to_find,
1600 budget - 1, 1608 budget - 1,
1601 not_at_start); 1609 not_at_start);
1602 } 1610 }
1603 1611
1604 1612
1605 int TextNode::EatsAtLeast(int still_to_find, 1613 intptr_t TextNode::EatsAtLeast(intptr_t still_to_find,
1606 int budget, 1614 intptr_t budget,
1607 bool not_at_start) { 1615 bool not_at_start) {
1608 int answer = Length(); 1616 intptr_t answer = Length();
1609 if (answer >= still_to_find) return answer; 1617 if (answer >= still_to_find) return answer;
1610 if (budget <= 0) return answer; 1618 if (budget <= 0) return answer;
1611 // We are not at start after this node so we set the last argument to 'true'. 1619 // We are not at start after this node so we set the last argument to 'true'.
1612 return answer + on_success()->EatsAtLeast(still_to_find - answer, 1620 return answer + on_success()->EatsAtLeast(still_to_find - answer,
1613 budget - 1, 1621 budget - 1,
1614 true); 1622 true);
1615 } 1623 }
1616 1624
1617 1625
1618 int NegativeLookaheadChoiceNode::EatsAtLeast(int still_to_find, 1626 intptr_t NegativeLookaheadChoiceNode::EatsAtLeast(intptr_t still_to_find,
1619 int budget, 1627 intptr_t budget,
1620 bool not_at_start) { 1628 bool not_at_start) {
1621 if (budget <= 0) return 0; 1629 if (budget <= 0) return 0;
1622 // Alternative 0 is the negative lookahead, alternative 1 is what comes 1630 // Alternative 0 is the negative lookahead, alternative 1 is what comes
1623 // afterwards. 1631 // afterwards.
1624 RegExpNode* node = alternatives_->at(1).node(); 1632 RegExpNode* node = (*alternatives_)[1].node();
1625 return node->EatsAtLeast(still_to_find, budget - 1, not_at_start); 1633 return node->EatsAtLeast(still_to_find, budget - 1, not_at_start);
1626 } 1634 }
1627 1635
1628 1636
1629 void NegativeLookaheadChoiceNode::GetQuickCheckDetails( 1637 void NegativeLookaheadChoiceNode::GetQuickCheckDetails(
1630 QuickCheckDetails* details, 1638 QuickCheckDetails* details,
1631 RegExpCompiler* compiler, 1639 RegExpCompiler* compiler,
1632 int filled_in, 1640 intptr_t filled_in,
1633 bool not_at_start) { 1641 bool not_at_start) {
1634 // Alternative 0 is the negative lookahead, alternative 1 is what comes 1642 // Alternative 0 is the negative lookahead, alternative 1 is what comes
1635 // afterwards. 1643 // afterwards.
1636 RegExpNode* node = alternatives_->at(1).node(); 1644 RegExpNode* node = (*alternatives_)[1].node();
1637 return node->GetQuickCheckDetails(details, compiler, filled_in, not_at_start); 1645 return node->GetQuickCheckDetails(details, compiler, filled_in, not_at_start);
1638 } 1646 }
1639 1647
1640 1648
1641 int ChoiceNode::EatsAtLeastHelper(int still_to_find, 1649 intptr_t ChoiceNode::EatsAtLeastHelper(intptr_t still_to_find,
1642 int budget, 1650 intptr_t budget,
1643 RegExpNode* ignore_this_node, 1651 RegExpNode* ignore_this_node,
1644 bool not_at_start) { 1652 bool not_at_start) {
1645 if (budget <= 0) return 0; 1653 if (budget <= 0) return 0;
1646 int min = 100; 1654 intptr_t min = 100;
1647 int choice_count = alternatives_->length(); 1655 intptr_t choice_count = alternatives_->length();
1648 budget = (budget - 1) / choice_count; 1656 budget = (budget - 1) / choice_count;
1649 for (int i = 0; i < choice_count; i++) { 1657 for (intptr_t i = 0; i < choice_count; i++) {
1650 RegExpNode* node = alternatives_->at(i).node(); 1658 RegExpNode* node = (*alternatives_)[i].node();
1651 if (node == ignore_this_node) continue; 1659 if (node == ignore_this_node) continue;
1652 int node_eats_at_least = 1660 intptr_t node_eats_at_least =
1653 node->EatsAtLeast(still_to_find, budget, not_at_start); 1661 node->EatsAtLeast(still_to_find, budget, not_at_start);
1654 if (node_eats_at_least < min) min = node_eats_at_least; 1662 if (node_eats_at_least < min) min = node_eats_at_least;
1655 if (min == 0) return 0; 1663 if (min == 0) return 0;
1656 } 1664 }
1657 return min; 1665 return min;
1658 } 1666 }
1659 1667
1660 1668
1661 int LoopChoiceNode::EatsAtLeast(int still_to_find, 1669 intptr_t LoopChoiceNode::EatsAtLeast(intptr_t still_to_find,
1662 int budget, 1670 intptr_t budget,
1663 bool not_at_start) { 1671 bool not_at_start) {
1664 return EatsAtLeastHelper(still_to_find, 1672 return EatsAtLeastHelper(still_to_find,
1665 budget - 1, 1673 budget - 1,
1666 loop_node_, 1674 loop_node_,
1667 not_at_start); 1675 not_at_start);
1668 } 1676 }
1669 1677
1670 1678
1671 int ChoiceNode::EatsAtLeast(int still_to_find, 1679 intptr_t ChoiceNode::EatsAtLeast(intptr_t still_to_find,
1672 int budget, 1680 intptr_t budget,
1673 bool not_at_start) { 1681 bool not_at_start) {
1674 return EatsAtLeastHelper(still_to_find, 1682 return EatsAtLeastHelper(still_to_find,
1675 budget, 1683 budget,
1676 NULL, 1684 NULL,
1677 not_at_start); 1685 not_at_start);
1678 } 1686 }
1679 1687
1680 1688
1681 // Takes the left-most 1-bit and smears it out, setting all bits to its right. 1689 // Takes the left-most 1-bit and smears it out, setting all bits to its right.
1682 static inline uint32_t SmearBitsRight(uint32_t v) { 1690 static inline uint32_t SmearBitsRight(uint32_t v) {
1683 v |= v >> 1; 1691 v |= v >> 1;
1684 v |= v >> 2; 1692 v |= v >> 2;
1685 v |= v >> 4; 1693 v |= v >> 4;
1686 v |= v >> 8; 1694 v |= v >> 8;
1687 v |= v >> 16; 1695 v |= v >> 16;
1688 return v; 1696 return v;
1689 } 1697 }
1690 1698
1691 1699
1692 bool QuickCheckDetails::Rationalize(bool asc) { 1700 bool QuickCheckDetails::Rationalize(bool asc) {
1693 bool found_useful_op = false; 1701 bool found_useful_op = false;
1694 uint32_t char_mask; 1702 uint32_t char_mask;
1695 if (asc) { 1703 if (asc) {
1696 char_mask = String::kMaxOneByteCharCode; 1704 char_mask = Symbols::kMaxOneCharCodeSymbol;
1697 } else { 1705 } else {
1698 char_mask = String::kMaxUtf16CodeUnit; 1706 char_mask = Utf16::kMaxCodeUnit;
1699 } 1707 }
1700 mask_ = 0; 1708 mask_ = 0;
1701 value_ = 0; 1709 value_ = 0;
1702 int char_shift = 0; 1710 intptr_t char_shift = 0;
1703 for (int i = 0; i < characters_; i++) { 1711 for (intptr_t i = 0; i < characters_; i++) {
1704 Position* pos = &positions_[i]; 1712 Position* pos = &positions_[i];
1705 if ((pos->mask & String::kMaxOneByteCharCode) != 0) { 1713 if ((pos->mask & Symbols::kMaxOneCharCodeSymbol) != 0) {
1706 found_useful_op = true; 1714 found_useful_op = true;
1707 } 1715 }
1708 mask_ |= (pos->mask & char_mask) << char_shift; 1716 mask_ |= (pos->mask & char_mask) << char_shift;
1709 value_ |= (pos->value & char_mask) << char_shift; 1717 value_ |= (pos->value & char_mask) << char_shift;
1710 char_shift += asc ? 8 : 16; 1718 char_shift += asc ? 8 : 16;
1711 } 1719 }
1712 return found_useful_op; 1720 return found_useful_op;
1713 } 1721 }
1714 1722
1715 1723
1716 bool RegExpNode::EmitQuickCheck(RegExpCompiler* compiler, 1724 bool RegExpNode::EmitQuickCheck(RegExpCompiler* compiler,
1717 Trace* bounds_check_trace, 1725 Trace* bounds_check_trace,
1718 Trace* trace, 1726 Trace* trace,
1719 bool preload_has_checked_bounds, 1727 bool preload_has_checked_bounds,
1720 Label* on_possible_success, 1728 BlockLabel* on_possible_success,
1721 QuickCheckDetails* details, 1729 QuickCheckDetails* details,
1722 bool fall_through_on_failure) { 1730 bool fall_through_on_failure) {
1723 if (details->characters() == 0) return false; 1731 if (details->characters() == 0) return false;
1724 GetQuickCheckDetails( 1732 GetQuickCheckDetails(
1725 details, compiler, 0, trace->at_start() == Trace::FALSE_VALUE); 1733 details, compiler, 0, trace->at_start() == Trace::FALSE_VALUE);
1726 if (details->cannot_match()) return false; 1734 if (details->cannot_match()) return false;
1727 if (!details->Rationalize(compiler->one_byte())) return false; 1735 if (!details->Rationalize(compiler->one_byte())) return false;
1728 DCHECK(details->characters() == 1 || 1736 ASSERT(details->characters() == 1 ||
1729 compiler->macro_assembler()->CanReadUnaligned()); 1737 compiler->macro_assembler()->CanReadUnaligned());
1730 uint32_t mask = details->mask(); 1738 uint32_t mask = details->mask();
1731 uint32_t value = details->value(); 1739 uint32_t value = details->value();
1732 1740
1733 RegExpMacroAssembler* assembler = compiler->macro_assembler(); 1741 RegExpMacroAssembler* assembler = compiler->macro_assembler();
1734 1742
1735 if (trace->characters_preloaded() != details->characters()) { 1743 if (trace->characters_preloaded() != details->characters()) {
1736 DCHECK(trace->cp_offset() == bounds_check_trace->cp_offset()); 1744 ASSERT(trace->cp_offset() == bounds_check_trace->cp_offset());
1737 // We are attempting to preload the minimum number of characters 1745 // We are attempting to preload the minimum number of characters
1738 // any choice would eat, so if the bounds check fails, then none of the 1746 // any choice would eat, so if the bounds check fails, then none of the
1739 // choices can succeed, so we can just immediately backtrack, rather 1747 // choices can succeed, so we can just immediately backtrack, rather
1740 // than go to the next choice. 1748 // than go to the next choice.
1741 assembler->LoadCurrentCharacter(trace->cp_offset(), 1749 assembler->LoadCurrentCharacter(trace->cp_offset(),
1742 bounds_check_trace->backtrack(), 1750 bounds_check_trace->backtrack(),
1743 !preload_has_checked_bounds, 1751 !preload_has_checked_bounds,
1744 details->characters()); 1752 details->characters());
1745 } 1753 }
1746 1754
1747 1755
1748 bool need_mask = true; 1756 bool need_mask = true;
1749 1757
1750 if (details->characters() == 1) { 1758 if (details->characters() == 1) {
1751 // If number of characters preloaded is 1 then we used a byte or 16 bit 1759 // If number of characters preloaded is 1 then we used a byte or 16 bit
1752 // load so the value is already masked down. 1760 // load so the value is already masked down.
1753 uint32_t char_mask; 1761 uint32_t char_mask;
1754 if (compiler->one_byte()) { 1762 if (compiler->one_byte()) {
1755 char_mask = String::kMaxOneByteCharCode; 1763 char_mask = Symbols::kMaxOneCharCodeSymbol;
1756 } else { 1764 } else {
1757 char_mask = String::kMaxUtf16CodeUnit; 1765 char_mask = Utf16::kMaxCodeUnit;
1758 } 1766 }
1759 if ((mask & char_mask) == char_mask) need_mask = false; 1767 if ((mask & char_mask) == char_mask) need_mask = false;
1760 mask &= char_mask; 1768 mask &= char_mask;
1761 } else { 1769 } else {
1762 // For 2-character preloads in one-byte mode or 1-character preloads in 1770 // For 2-character preloads in one-byte mode or 1-character preloads in
1763 // two-byte mode we also use a 16 bit load with zero extend. 1771 // two-byte mode we also use a 16 bit load with zero extend.
1764 if (details->characters() == 2 && compiler->one_byte()) { 1772 if (details->characters() == 2 && compiler->one_byte()) {
1765 if ((mask & 0xffff) == 0xffff) need_mask = false; 1773 if ((mask & 0xffff) == 0xffff) need_mask = false;
1766 } else if (details->characters() == 1 && !compiler->one_byte()) { 1774 } else if (details->characters() == 1 && !compiler->one_byte()) {
1767 if ((mask & 0xffff) == 0xffff) need_mask = false; 1775 if ((mask & 0xffff) == 0xffff) need_mask = false;
(...skipping 22 matching lines...) Expand all
1790 // Here is the meat of GetQuickCheckDetails (see also the comment on the 1798 // Here is the meat of GetQuickCheckDetails (see also the comment on the
1791 // super-class in the .h file). 1799 // super-class in the .h file).
1792 // 1800 //
1793 // We iterate along the text object, building up for each character a 1801 // We iterate along the text object, building up for each character a
1794 // mask and value that can be used to test for a quick failure to match. 1802 // mask and value that can be used to test for a quick failure to match.
1795 // The masks and values for the positions will be combined into a single 1803 // The masks and values for the positions will be combined into a single
1796 // machine word for the current character width in order to be used in 1804 // machine word for the current character width in order to be used in
1797 // generating a quick check. 1805 // generating a quick check.
1798 void TextNode::GetQuickCheckDetails(QuickCheckDetails* details, 1806 void TextNode::GetQuickCheckDetails(QuickCheckDetails* details,
1799 RegExpCompiler* compiler, 1807 RegExpCompiler* compiler,
1800 int characters_filled_in, 1808 intptr_t characters_filled_in,
1801 bool not_at_start) { 1809 bool not_at_start) {
1802 Isolate* isolate = compiler->macro_assembler()->zone()->isolate(); 1810 #if defined(__GNUC__)
1803 DCHECK(characters_filled_in < details->characters()); 1811 // TODO(zerny): Make the combination code byte-order independent.
1804 int characters = details->characters(); 1812 ASSERT(details->characters() == 1 ||
1805 int char_mask; 1813 (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__));
1814 #endif
1815 ASSERT(characters_filled_in < details->characters());
1816 intptr_t characters = details->characters();
1817 intptr_t char_mask;
1806 if (compiler->one_byte()) { 1818 if (compiler->one_byte()) {
1807 char_mask = String::kMaxOneByteCharCode; 1819 char_mask = Symbols::kMaxOneCharCodeSymbol;
1808 } else { 1820 } else {
1809 char_mask = String::kMaxUtf16CodeUnit; 1821 char_mask = Utf16::kMaxCodeUnit;
1810 } 1822 }
1811 for (int k = 0; k < elms_->length(); k++) { 1823 for (intptr_t k = 0; k < elms_->length(); k++) {
1812 TextElement elm = elms_->at(k); 1824 TextElement elm = elms_->At(k);
1813 if (elm.text_type() == TextElement::ATOM) { 1825 if (elm.text_type() == TextElement::ATOM) {
1814 Vector<const uc16> quarks = elm.atom()->data(); 1826 ZoneGrowableArray<uint16_t>* quarks = elm.atom()->data();
1815 for (int i = 0; i < characters && i < quarks.length(); i++) { 1827 for (intptr_t i = 0; i < characters && i < quarks->length(); i++) {
1816 QuickCheckDetails::Position* pos = 1828 QuickCheckDetails::Position* pos =
1817 details->positions(characters_filled_in); 1829 details->positions(characters_filled_in);
1818 uc16 c = quarks[i]; 1830 uint16_t c = quarks->At(i);
1819 if (c > char_mask) { 1831 if (c > char_mask) {
1820 // If we expect a non-Latin1 character from an one-byte string, 1832 // If we expect a non-Latin1 character from an one-byte string,
1821 // there is no way we can match. Not even case-independent 1833 // there is no way we can match. Not even case independent
1822 // matching can turn an Latin1 character into non-Latin1 or 1834 // matching can turn an Latin1 character into non-Latin1 or
1823 // vice versa. 1835 // vice versa.
1824 // TODO(dcarney): issue 3550. Verify that this works as expected. 1836 // TODO(dcarney): issue 3550. Verify that this works as expected.
1825 // For example, \u0178 is uppercase of \u00ff (y-umlaut). 1837 // For example, \u0178 is uppercase of \u00ff (y-umlaut).
1826 details->set_cannot_match(); 1838 details->set_cannot_match();
1827 pos->determines_perfectly = false; 1839 pos->determines_perfectly = false;
1828 return; 1840 return;
1829 } 1841 }
1830 if (compiler->ignore_case()) { 1842 if (compiler->ignore_case()) {
1831 unibrow::uchar chars[unibrow::Ecma262UnCanonicalize::kMaxWidth]; 1843 int32_t chars[unibrow::Ecma262UnCanonicalize::kMaxWidth];
1832 int length = GetCaseIndependentLetters(isolate, c, 1844 intptr_t length =
1833 compiler->one_byte(), chars); 1845 GetCaseIndependentLetters(c, compiler->one_byte(), chars);
1834 DCHECK(length != 0); // Can only happen if c > char_mask (see above). 1846 ASSERT(length != 0); // Can only happen if c > char_mask (see above).
1835 if (length == 1) { 1847 if (length == 1) {
1836 // This letter has no case equivalents, so it's nice and simple 1848 // This letter has no case equivalents, so it's nice and simple
1837 // and the mask-compare will determine definitely whether we have 1849 // and the mask-compare will determine definitely whether we have
1838 // a match at this character position. 1850 // a match at this character position.
1839 pos->mask = char_mask; 1851 pos->mask = char_mask;
1840 pos->value = c; 1852 pos->value = c;
1841 pos->determines_perfectly = true; 1853 pos->determines_perfectly = true;
1842 } else { 1854 } else {
1843 uint32_t common_bits = char_mask; 1855 uint32_t common_bits = char_mask;
1844 uint32_t bits = chars[0]; 1856 uint32_t bits = chars[0];
1845 for (int j = 1; j < length; j++) { 1857 for (intptr_t j = 1; j < length; j++) {
1846 uint32_t differing_bits = ((chars[j] & common_bits) ^ bits); 1858 uint32_t differing_bits = ((chars[j] & common_bits) ^ bits);
1847 common_bits ^= differing_bits; 1859 common_bits ^= differing_bits;
1848 bits &= common_bits; 1860 bits &= common_bits;
1849 } 1861 }
1850 // If length is 2 and common bits has only one zero in it then 1862 // If length is 2 and common bits has only one zero in it then
1851 // our mask and compare instruction will determine definitely 1863 // our mask and compare instruction will determine definitely
1852 // whether we have a match at this character position. Otherwise 1864 // whether we have a match at this character position. Otherwise
1853 // it can only be an approximate check. 1865 // it can only be an approximate check.
1854 uint32_t one_zero = (common_bits | ~char_mask); 1866 uint32_t one_zero = (common_bits | ~char_mask);
1855 if (length == 2 && ((~one_zero) & ((~one_zero) - 1)) == 0) { 1867 if (length == 2 && ((~one_zero) & ((~one_zero) - 1)) == 0) {
1856 pos->determines_perfectly = true; 1868 pos->determines_perfectly = true;
1857 } 1869 }
1858 pos->mask = common_bits; 1870 pos->mask = common_bits;
1859 pos->value = bits; 1871 pos->value = bits;
1860 } 1872 }
1861 } else { 1873 } else {
1862 // Don't ignore case. Nice simple case where the mask-compare will 1874 // Don't ignore case. Nice simple case where the mask-compare will
1863 // determine definitely whether we have a match at this character 1875 // determine definitely whether we have a match at this character
1864 // position. 1876 // position.
1865 pos->mask = char_mask; 1877 pos->mask = char_mask;
1866 pos->value = c; 1878 pos->value = c;
1867 pos->determines_perfectly = true; 1879 pos->determines_perfectly = true;
1868 } 1880 }
1869 characters_filled_in++; 1881 characters_filled_in++;
1870 DCHECK(characters_filled_in <= details->characters()); 1882 ASSERT(characters_filled_in <= details->characters());
1871 if (characters_filled_in == details->characters()) { 1883 if (characters_filled_in == details->characters()) {
1872 return; 1884 return;
1873 } 1885 }
1874 } 1886 }
1875 } else { 1887 } else {
1876 QuickCheckDetails::Position* pos = 1888 QuickCheckDetails::Position* pos =
1877 details->positions(characters_filled_in); 1889 details->positions(characters_filled_in);
1878 RegExpCharacterClass* tree = elm.char_class(); 1890 RegExpCharacterClass* tree = elm.char_class();
1879 ZoneList<CharacterRange>* ranges = tree->ranges(zone()); 1891 ZoneGrowableArray<CharacterRange>* ranges = tree->ranges();
1880 if (tree->is_negated()) { 1892 if (tree->is_negated()) {
1881 // A quick check uses multi-character mask and compare. There is no 1893 // A quick check uses multi-character mask and compare. There is no
1882 // useful way to incorporate a negative char class into this scheme 1894 // useful way to incorporate a negative char class into this scheme
1883 // so we just conservatively create a mask and value that will always 1895 // so we just conservatively create a mask and value that will always
1884 // succeed. 1896 // succeed.
1885 pos->mask = 0; 1897 pos->mask = 0;
1886 pos->value = 0; 1898 pos->value = 0;
1887 } else { 1899 } else {
1888 int first_range = 0; 1900 intptr_t first_range = 0;
1889 while (ranges->at(first_range).from() > char_mask) { 1901 while (ranges->At(first_range).from() > char_mask) {
1890 first_range++; 1902 first_range++;
1891 if (first_range == ranges->length()) { 1903 if (first_range == ranges->length()) {
1892 details->set_cannot_match(); 1904 details->set_cannot_match();
1893 pos->determines_perfectly = false; 1905 pos->determines_perfectly = false;
1894 return; 1906 return;
1895 } 1907 }
1896 } 1908 }
1897 CharacterRange range = ranges->at(first_range); 1909 CharacterRange range = ranges->At(first_range);
1898 uc16 from = range.from(); 1910 uint16_t from = range.from();
1899 uc16 to = range.to(); 1911 uint16_t to = range.to();
1900 if (to > char_mask) { 1912 if (to > char_mask) {
1901 to = char_mask; 1913 to = char_mask;
1902 } 1914 }
1903 uint32_t differing_bits = (from ^ to); 1915 uint32_t differing_bits = (from ^ to);
1904 // A mask and compare is only perfect if the differing bits form a 1916 // A mask and compare is only perfect if the differing bits form a
1905 // number like 00011111 with one single block of trailing 1s. 1917 // number like 00011111 with one single block of trailing 1s.
1906 if ((differing_bits & (differing_bits + 1)) == 0 && 1918 if ((differing_bits & (differing_bits + 1)) == 0 &&
1907 from + differing_bits == to) { 1919 from + differing_bits == to) {
1908 pos->determines_perfectly = true; 1920 pos->determines_perfectly = true;
1909 } 1921 }
1910 uint32_t common_bits = ~SmearBitsRight(differing_bits); 1922 uint32_t common_bits = ~SmearBitsRight(differing_bits);
1911 uint32_t bits = (from & common_bits); 1923 uint32_t bits = (from & common_bits);
1912 for (int i = first_range + 1; i < ranges->length(); i++) { 1924 for (intptr_t i = first_range + 1; i < ranges->length(); i++) {
1913 CharacterRange range = ranges->at(i); 1925 CharacterRange range = ranges->At(i);
1914 uc16 from = range.from(); 1926 uint16_t from = range.from();
1915 uc16 to = range.to(); 1927 uint16_t to = range.to();
1916 if (from > char_mask) continue; 1928 if (from > char_mask) continue;
1917 if (to > char_mask) to = char_mask; 1929 if (to > char_mask) to = char_mask;
1918 // Here we are combining more ranges into the mask and compare 1930 // Here we are combining more ranges into the mask and compare
1919 // value. With each new range the mask becomes more sparse and 1931 // value. With each new range the mask becomes more sparse and
1920 // so the chances of a false positive rise. A character class 1932 // so the chances of a false positive rise. A character class
1921 // with multiple ranges is assumed never to be equivalent to a 1933 // with multiple ranges is assumed never to be equivalent to a
1922 // mask and compare operation. 1934 // mask and compare operation.
1923 pos->determines_perfectly = false; 1935 pos->determines_perfectly = false;
1924 uint32_t new_common_bits = (from ^ to); 1936 uint32_t new_common_bits = (from ^ to);
1925 new_common_bits = ~SmearBitsRight(new_common_bits); 1937 new_common_bits = ~SmearBitsRight(new_common_bits);
1926 common_bits &= new_common_bits; 1938 common_bits &= new_common_bits;
1927 bits &= new_common_bits; 1939 bits &= new_common_bits;
1928 uint32_t differing_bits = (from & common_bits) ^ bits; 1940 uint32_t differing_bits = (from & common_bits) ^ bits;
1929 common_bits ^= differing_bits; 1941 common_bits ^= differing_bits;
1930 bits &= common_bits; 1942 bits &= common_bits;
1931 } 1943 }
1932 pos->mask = common_bits; 1944 pos->mask = common_bits;
1933 pos->value = bits; 1945 pos->value = bits;
1934 } 1946 }
1935 characters_filled_in++; 1947 characters_filled_in++;
1936 DCHECK(characters_filled_in <= details->characters()); 1948 ASSERT(characters_filled_in <= details->characters());
1937 if (characters_filled_in == details->characters()) { 1949 if (characters_filled_in == details->characters()) {
1938 return; 1950 return;
1939 } 1951 }
1940 } 1952 }
1941 } 1953 }
1942 DCHECK(characters_filled_in != details->characters()); 1954 ASSERT(characters_filled_in != details->characters());
1943 if (!details->cannot_match()) { 1955 if (!details->cannot_match()) {
1944 on_success()-> GetQuickCheckDetails(details, 1956 on_success()-> GetQuickCheckDetails(details,
1945 compiler, 1957 compiler,
1946 characters_filled_in, 1958 characters_filled_in,
1947 true); 1959 true);
1948 } 1960 }
1949 } 1961 }
1950 1962
1951 1963
1952 void QuickCheckDetails::Clear() { 1964 void QuickCheckDetails::Clear() {
1953 for (int i = 0; i < characters_; i++) { 1965 for (int i = 0; i < characters_; i++) {
1954 positions_[i].mask = 0; 1966 positions_[i].mask = 0;
1955 positions_[i].value = 0; 1967 positions_[i].value = 0;
1956 positions_[i].determines_perfectly = false; 1968 positions_[i].determines_perfectly = false;
1957 } 1969 }
1958 characters_ = 0; 1970 characters_ = 0;
1959 } 1971 }
1960 1972
1961 1973
1962 void QuickCheckDetails::Advance(int by, bool one_byte) { 1974 void QuickCheckDetails::Advance(intptr_t by, bool one_byte) {
1963 DCHECK(by >= 0); 1975 ASSERT(by >= 0);
1964 if (by >= characters_) { 1976 if (by >= characters_) {
1965 Clear(); 1977 Clear();
1966 return; 1978 return;
1967 } 1979 }
1968 for (int i = 0; i < characters_ - by; i++) { 1980 for (intptr_t i = 0; i < characters_ - by; i++) {
1969 positions_[i] = positions_[by + i]; 1981 positions_[i] = positions_[by + i];
1970 } 1982 }
1971 for (int i = characters_ - by; i < characters_; i++) { 1983 for (intptr_t i = characters_ - by; i < characters_; i++) {
1972 positions_[i].mask = 0; 1984 positions_[i].mask = 0;
1973 positions_[i].value = 0; 1985 positions_[i].value = 0;
1974 positions_[i].determines_perfectly = false; 1986 positions_[i].determines_perfectly = false;
1975 } 1987 }
1976 characters_ -= by; 1988 characters_ -= by;
1977 // We could change mask_ and value_ here but we would never advance unless 1989 // We could change mask_ and value_ here but we would never advance unless
1978 // they had already been used in a check and they won't be used again because 1990 // they had already been used in a check and they won't be used again because
1979 // it would gain us nothing. So there's no point. 1991 // it would gain us nothing. So there's no point.
1980 } 1992 }
1981 1993
1982 1994
1983 void QuickCheckDetails::Merge(QuickCheckDetails* other, int from_index) { 1995 void QuickCheckDetails::Merge(QuickCheckDetails* other, intptr_t from_index) {
1984 DCHECK(characters_ == other->characters_); 1996 ASSERT(characters_ == other->characters_);
1985 if (other->cannot_match_) { 1997 if (other->cannot_match_) {
1986 return; 1998 return;
1987 } 1999 }
1988 if (cannot_match_) { 2000 if (cannot_match_) {
1989 *this = *other; 2001 *this = *other;
1990 return; 2002 return;
1991 } 2003 }
1992 for (int i = from_index; i < characters_; i++) { 2004 for (intptr_t i = from_index; i < characters_; i++) {
1993 QuickCheckDetails::Position* pos = positions(i); 2005 QuickCheckDetails::Position* pos = positions(i);
1994 QuickCheckDetails::Position* other_pos = other->positions(i); 2006 QuickCheckDetails::Position* other_pos = other->positions(i);
1995 if (pos->mask != other_pos->mask || 2007 if (pos->mask != other_pos->mask ||
1996 pos->value != other_pos->value || 2008 pos->value != other_pos->value ||
1997 !other_pos->determines_perfectly) { 2009 !other_pos->determines_perfectly) {
1998 // Our mask-compare operation will be approximate unless we have the 2010 // Our mask-compare operation will be approximate unless we have the
1999 // exact same operation on both sides of the alternation. 2011 // exact same operation on both sides of the alternation.
2000 pos->determines_perfectly = false; 2012 pos->determines_perfectly = false;
2001 } 2013 }
2002 pos->mask &= other_pos->mask; 2014 pos->mask &= other_pos->mask;
2003 pos->value &= pos->mask; 2015 pos->value &= pos->mask;
2004 other_pos->value &= pos->mask; 2016 other_pos->value &= pos->mask;
2005 uc16 differing_bits = (pos->value ^ other_pos->value); 2017 uint16_t differing_bits = (pos->value ^ other_pos->value);
2006 pos->mask &= ~differing_bits; 2018 pos->mask &= ~differing_bits;
2007 pos->value &= pos->mask; 2019 pos->value &= pos->mask;
2008 } 2020 }
2009 } 2021 }
2010 2022
2011 2023
2012 class VisitMarker { 2024 class VisitMarker : public ValueObject {
2013 public: 2025 public:
2014 explicit VisitMarker(NodeInfo* info) : info_(info) { 2026 explicit VisitMarker(NodeInfo* info) : info_(info) {
2015 DCHECK(!info->visited); 2027 ASSERT(!info->visited);
2016 info->visited = true; 2028 info->visited = true;
2017 } 2029 }
2018 ~VisitMarker() { 2030 ~VisitMarker() {
2019 info_->visited = false; 2031 info_->visited = false;
2020 } 2032 }
2021 private: 2033 private:
2022 NodeInfo* info_; 2034 NodeInfo* info_;
2023 }; 2035 };
2024 2036
2025 2037
2026 RegExpNode* SeqRegExpNode::FilterOneByte(int depth, bool ignore_case) { 2038 RegExpNode* SeqRegExpNode::FilterOneByte(intptr_t depth, bool ignore_case) {
2027 if (info()->replacement_calculated) return replacement(); 2039 if (info()->replacement_calculated) return replacement();
2028 if (depth < 0) return this; 2040 if (depth < 0) return this;
2029 DCHECK(!info()->visited); 2041 ASSERT(!info()->visited);
2030 VisitMarker marker(info()); 2042 VisitMarker marker(info());
2031 return FilterSuccessor(depth - 1, ignore_case); 2043 return FilterSuccessor(depth - 1, ignore_case);
2032 } 2044 }
2033 2045
2034 2046
2035 RegExpNode* SeqRegExpNode::FilterSuccessor(int depth, bool ignore_case) { 2047 RegExpNode* SeqRegExpNode::FilterSuccessor(intptr_t depth, bool ignore_case) {
2036 RegExpNode* next = on_success_->FilterOneByte(depth - 1, ignore_case); 2048 RegExpNode* next = on_success_->FilterOneByte(depth - 1, ignore_case);
2037 if (next == NULL) return set_replacement(NULL); 2049 if (next == NULL) return set_replacement(NULL);
2038 on_success_ = next; 2050 on_success_ = next;
2039 return set_replacement(this); 2051 return set_replacement(this);
2040 } 2052 }
2041 2053
2042 2054
2043 // We need to check for the following characters: 0x39c 0x3bc 0x178. 2055 // We need to check for the following characters: 0x39c 0x3bc 0x178.
2044 static inline bool RangeContainsLatin1Equivalents(CharacterRange range) { 2056 static inline bool RangeContainsLatin1Equivalents(CharacterRange range) {
2045 // TODO(dcarney): this could be a lot more efficient. 2057 // TODO(dcarney): this could be a lot more efficient.
2046 return range.Contains(0x39c) || 2058 return range.Contains(0x39c) ||
2047 range.Contains(0x3bc) || range.Contains(0x178); 2059 range.Contains(0x3bc) || range.Contains(0x178);
2048 } 2060 }
2049 2061
2050 2062
2051 static bool RangesContainLatin1Equivalents(ZoneList<CharacterRange>* ranges) { 2063 static bool RangesContainLatin1Equivalents(
2052 for (int i = 0; i < ranges->length(); i++) { 2064 ZoneGrowableArray<CharacterRange>* ranges) {
2065 for (intptr_t i = 0; i < ranges->length(); i++) {
2053 // TODO(dcarney): this could be a lot more efficient. 2066 // TODO(dcarney): this could be a lot more efficient.
2054 if (RangeContainsLatin1Equivalents(ranges->at(i))) return true; 2067 if (RangeContainsLatin1Equivalents(ranges->At(i))) return true;
2055 } 2068 }
2056 return false; 2069 return false;
2057 } 2070 }
2058 2071
2059 2072
2060 RegExpNode* TextNode::FilterOneByte(int depth, bool ignore_case) { 2073 static uint16_t ConvertNonLatin1ToLatin1(uint16_t c) {
2074 ASSERT(c > Symbols::kMaxOneCharCodeSymbol);
2075 switch (c) {
2076 // This are equivalent characters in unicode.
2077 case 0x39c:
2078 case 0x3bc:
2079 return 0xb5;
2080 // This is an uppercase of a Latin-1 character
2081 // outside of Latin-1.
2082 case 0x178:
2083 return 0xff;
2084 }
2085 return 0;
2086 }
2087
2088
2089 RegExpNode* TextNode::FilterOneByte(intptr_t depth, bool ignore_case) {
2061 if (info()->replacement_calculated) return replacement(); 2090 if (info()->replacement_calculated) return replacement();
2062 if (depth < 0) return this; 2091 if (depth < 0) return this;
2063 DCHECK(!info()->visited); 2092 ASSERT(!info()->visited);
2064 VisitMarker marker(info()); 2093 VisitMarker marker(info());
2065 int element_count = elms_->length(); 2094 intptr_t element_count = elms_->length();
2066 for (int i = 0; i < element_count; i++) { 2095 for (intptr_t i = 0; i < element_count; i++) {
2067 TextElement elm = elms_->at(i); 2096 TextElement elm = elms_->At(i);
2068 if (elm.text_type() == TextElement::ATOM) { 2097 if (elm.text_type() == TextElement::ATOM) {
2069 Vector<const uc16> quarks = elm.atom()->data(); 2098 ZoneGrowableArray<uint16_t>* quarks = elm.atom()->data();
2070 for (int j = 0; j < quarks.length(); j++) { 2099 for (intptr_t j = 0; j < quarks->length(); j++) {
2071 uint16_t c = quarks[j]; 2100 uint16_t c = quarks->At(j);
2072 if (c <= String::kMaxOneByteCharCode) continue; 2101 if (c <= Symbols::kMaxOneCharCodeSymbol) continue;
2073 if (!ignore_case) return set_replacement(NULL); 2102 if (!ignore_case) return set_replacement(NULL);
2074 // Here, we need to check for characters whose upper and lower cases 2103 // Here, we need to check for characters whose upper and lower cases
2075 // are outside the Latin-1 range. 2104 // are outside the Latin-1 range.
2076 uint16_t converted = unibrow::Latin1::ConvertNonLatin1ToLatin1(c); 2105 uint16_t converted = ConvertNonLatin1ToLatin1(c);
2077 // Character is outside Latin-1 completely 2106 // Character is outside Latin-1 completely
2078 if (converted == 0) return set_replacement(NULL); 2107 if (converted == 0) return set_replacement(NULL);
2079 // Convert quark to Latin-1 in place. 2108 // Convert quark to Latin-1 in place.
2080 uint16_t* copy = const_cast<uint16_t*>(quarks.start()); 2109 (*quarks)[0] = converted;
2081 copy[j] = converted;
2082 } 2110 }
2083 } else { 2111 } else {
2084 DCHECK(elm.text_type() == TextElement::CHAR_CLASS); 2112 ASSERT(elm.text_type() == TextElement::CHAR_CLASS);
2085 RegExpCharacterClass* cc = elm.char_class(); 2113 RegExpCharacterClass* cc = elm.char_class();
2086 ZoneList<CharacterRange>* ranges = cc->ranges(zone()); 2114 ZoneGrowableArray<CharacterRange>* ranges = cc->ranges();
2087 if (!CharacterRange::IsCanonical(ranges)) { 2115 if (!CharacterRange::IsCanonical(ranges)) {
2088 CharacterRange::Canonicalize(ranges); 2116 CharacterRange::Canonicalize(ranges);
2089 } 2117 }
2090 // Now they are in order so we only need to look at the first. 2118 // Now they are in order so we only need to look at the first.
2091 int range_count = ranges->length(); 2119 intptr_t range_count = ranges->length();
2092 if (cc->is_negated()) { 2120 if (cc->is_negated()) {
2093 if (range_count != 0 && 2121 if (range_count != 0 &&
2094 ranges->at(0).from() == 0 && 2122 ranges->At(0).from() == 0 &&
2095 ranges->at(0).to() >= String::kMaxOneByteCharCode) { 2123 ranges->At(0).to() >= Symbols::kMaxOneCharCodeSymbol) {
2096 // This will be handled in a later filter. 2124 // This will be handled in a later filter.
2097 if (ignore_case && RangesContainLatin1Equivalents(ranges)) continue; 2125 if (ignore_case && RangesContainLatin1Equivalents(ranges)) continue;
2098 return set_replacement(NULL); 2126 return set_replacement(NULL);
2099 } 2127 }
2100 } else { 2128 } else {
2101 if (range_count == 0 || 2129 if (range_count == 0 ||
2102 ranges->at(0).from() > String::kMaxOneByteCharCode) { 2130 ranges->At(0).from() > Symbols::kMaxOneCharCodeSymbol) {
2103 // This will be handled in a later filter. 2131 // This will be handled in a later filter.
2104 if (ignore_case && RangesContainLatin1Equivalents(ranges)) continue; 2132 if (ignore_case && RangesContainLatin1Equivalents(ranges)) continue;
2105 return set_replacement(NULL); 2133 return set_replacement(NULL);
2106 } 2134 }
2107 } 2135 }
2108 } 2136 }
2109 } 2137 }
2110 return FilterSuccessor(depth - 1, ignore_case); 2138 return FilterSuccessor(depth - 1, ignore_case);
2111 } 2139 }
2112 2140
2113 2141
2114 RegExpNode* LoopChoiceNode::FilterOneByte(int depth, bool ignore_case) { 2142 RegExpNode* LoopChoiceNode::FilterOneByte(intptr_t depth, bool ignore_case) {
2115 if (info()->replacement_calculated) return replacement(); 2143 if (info()->replacement_calculated) return replacement();
2116 if (depth < 0) return this; 2144 if (depth < 0) return this;
2117 if (info()->visited) return this; 2145 if (info()->visited) return this;
2118 { 2146 {
2119 VisitMarker marker(info()); 2147 VisitMarker marker(info());
2120 2148
2121 RegExpNode* continue_replacement = 2149 RegExpNode* continue_replacement =
2122 continue_node_->FilterOneByte(depth - 1, ignore_case); 2150 continue_node_->FilterOneByte(depth - 1, ignore_case);
2123 // If we can't continue after the loop then there is no sense in doing the 2151 // If we can't continue after the loop then there is no sense in doing the
2124 // loop. 2152 // loop.
2125 if (continue_replacement == NULL) return set_replacement(NULL); 2153 if (continue_replacement == NULL) return set_replacement(NULL);
2126 } 2154 }
2127 2155
2128 return ChoiceNode::FilterOneByte(depth - 1, ignore_case); 2156 return ChoiceNode::FilterOneByte(depth - 1, ignore_case);
2129 } 2157 }
2130 2158
2131 2159
2132 RegExpNode* ChoiceNode::FilterOneByte(int depth, bool ignore_case) { 2160 RegExpNode* ChoiceNode::FilterOneByte(intptr_t depth, bool ignore_case) {
2133 if (info()->replacement_calculated) return replacement(); 2161 if (info()->replacement_calculated) return replacement();
2134 if (depth < 0) return this; 2162 if (depth < 0) return this;
2135 if (info()->visited) return this; 2163 if (info()->visited) return this;
2136 VisitMarker marker(info()); 2164 VisitMarker marker(info());
2137 int choice_count = alternatives_->length(); 2165 intptr_t choice_count = alternatives_->length();
2138 2166
2139 for (int i = 0; i < choice_count; i++) { 2167 for (intptr_t i = 0; i < choice_count; i++) {
2140 GuardedAlternative alternative = alternatives_->at(i); 2168 GuardedAlternative alternative = alternatives_->At(i);
2141 if (alternative.guards() != NULL && alternative.guards()->length() != 0) { 2169 if (alternative.guards() != NULL && alternative.guards()->length() != 0) {
2142 set_replacement(this); 2170 set_replacement(this);
2143 return this; 2171 return this;
2144 } 2172 }
2145 } 2173 }
2146 2174
2147 int surviving = 0; 2175 intptr_t surviving = 0;
2148 RegExpNode* survivor = NULL; 2176 RegExpNode* survivor = NULL;
2149 for (int i = 0; i < choice_count; i++) { 2177 for (intptr_t i = 0; i < choice_count; i++) {
2150 GuardedAlternative alternative = alternatives_->at(i); 2178 GuardedAlternative alternative = alternatives_->At(i);
2151 RegExpNode* replacement = 2179 RegExpNode* replacement =
2152 alternative.node()->FilterOneByte(depth - 1, ignore_case); 2180 alternative.node()->FilterOneByte(depth - 1, ignore_case);
2153 DCHECK(replacement != this); // No missing EMPTY_MATCH_CHECK. 2181 ASSERT(replacement != this); // No missing EMPTY_MATCH_CHECK.
2154 if (replacement != NULL) { 2182 if (replacement != NULL) {
2155 alternatives_->at(i).set_node(replacement); 2183 (*alternatives_)[i].set_node(replacement);
2156 surviving++; 2184 surviving++;
2157 survivor = replacement; 2185 survivor = replacement;
2158 } 2186 }
2159 } 2187 }
2160 if (surviving < 2) return set_replacement(survivor); 2188 if (surviving < 2) return set_replacement(survivor);
2161 2189
2162 set_replacement(this); 2190 set_replacement(this);
2163 if (surviving == choice_count) { 2191 if (surviving == choice_count) {
2164 return this; 2192 return this;
2165 } 2193 }
2166 // Only some of the nodes survived the filtering. We need to rebuild the 2194 // Only some of the nodes survived the filtering. We need to rebuild the
2167 // alternatives list. 2195 // alternatives list.
2168 ZoneList<GuardedAlternative>* new_alternatives = 2196 ZoneGrowableArray<GuardedAlternative>* new_alternatives =
2169 new(zone()) ZoneList<GuardedAlternative>(surviving, zone()); 2197 new(I) ZoneGrowableArray<GuardedAlternative>(surviving);
2170 for (int i = 0; i < choice_count; i++) { 2198 for (intptr_t i = 0; i < choice_count; i++) {
2171 RegExpNode* replacement = 2199 RegExpNode* replacement =
2172 alternatives_->at(i).node()->FilterOneByte(depth - 1, ignore_case); 2200 (*alternatives_)[i].node()->FilterOneByte(depth - 1, ignore_case);
2173 if (replacement != NULL) { 2201 if (replacement != NULL) {
2174 alternatives_->at(i).set_node(replacement); 2202 (*alternatives_)[i].set_node(replacement);
2175 new_alternatives->Add(alternatives_->at(i), zone()); 2203 new_alternatives->Add((*alternatives_)[i]);
2176 } 2204 }
2177 } 2205 }
2178 alternatives_ = new_alternatives; 2206 alternatives_ = new_alternatives;
2179 return this; 2207 return this;
2180 } 2208 }
2181 2209
2182 2210
2183 RegExpNode* NegativeLookaheadChoiceNode::FilterOneByte(int depth, 2211 RegExpNode* NegativeLookaheadChoiceNode::FilterOneByte(intptr_t depth,
2184 bool ignore_case) { 2212 bool ignore_case) {
2185 if (info()->replacement_calculated) return replacement(); 2213 if (info()->replacement_calculated) return replacement();
2186 if (depth < 0) return this; 2214 if (depth < 0) return this;
2187 if (info()->visited) return this; 2215 if (info()->visited) return this;
2188 VisitMarker marker(info()); 2216 VisitMarker marker(info());
2189 // Alternative 0 is the negative lookahead, alternative 1 is what comes 2217 // Alternative 0 is the negative lookahead, alternative 1 is what comes
2190 // afterwards. 2218 // afterwards.
2191 RegExpNode* node = alternatives_->at(1).node(); 2219 RegExpNode* node = (*alternatives_)[1].node();
2192 RegExpNode* replacement = node->FilterOneByte(depth - 1, ignore_case); 2220 RegExpNode* replacement = node->FilterOneByte(depth - 1, ignore_case);
2193 if (replacement == NULL) return set_replacement(NULL); 2221 if (replacement == NULL) return set_replacement(NULL);
2194 alternatives_->at(1).set_node(replacement); 2222 (*alternatives_)[1].set_node(replacement);
2195 2223
2196 RegExpNode* neg_node = alternatives_->at(0).node(); 2224 RegExpNode* neg_node = (*alternatives_)[0].node();
2197 RegExpNode* neg_replacement = neg_node->FilterOneByte(depth - 1, ignore_case); 2225 RegExpNode* neg_replacement = neg_node->FilterOneByte(depth - 1, ignore_case);
2198 // If the negative lookahead is always going to fail then 2226 // If the negative lookahead is always going to fail then
2199 // we don't need to check it. 2227 // we don't need to check it.
2200 if (neg_replacement == NULL) return set_replacement(replacement); 2228 if (neg_replacement == NULL) return set_replacement(replacement);
2201 alternatives_->at(0).set_node(neg_replacement); 2229 (*alternatives_)[0].set_node(neg_replacement);
2202 return set_replacement(this); 2230 return set_replacement(this);
2203 } 2231 }
2204 2232
2205 2233
2206 void LoopChoiceNode::GetQuickCheckDetails(QuickCheckDetails* details, 2234 void LoopChoiceNode::GetQuickCheckDetails(QuickCheckDetails* details,
2207 RegExpCompiler* compiler, 2235 RegExpCompiler* compiler,
2208 int characters_filled_in, 2236 intptr_t characters_filled_in,
2209 bool not_at_start) { 2237 bool not_at_start) {
2210 if (body_can_be_zero_length_ || info()->visited) return; 2238 if (body_can_be_zero_length_ || info()->visited) return;
2211 VisitMarker marker(info()); 2239 VisitMarker marker(info());
2212 return ChoiceNode::GetQuickCheckDetails(details, 2240 return ChoiceNode::GetQuickCheckDetails(details,
2213 compiler, 2241 compiler,
2214 characters_filled_in, 2242 characters_filled_in,
2215 not_at_start); 2243 not_at_start);
2216 } 2244 }
2217 2245
2218 2246
2219 void LoopChoiceNode::FillInBMInfo(int offset, 2247 void LoopChoiceNode::FillInBMInfo(intptr_t offset,
2220 int budget, 2248 intptr_t budget,
2221 BoyerMooreLookahead* bm, 2249 BoyerMooreLookahead* bm,
2222 bool not_at_start) { 2250 bool not_at_start) {
2223 if (body_can_be_zero_length_ || budget <= 0) { 2251 if (body_can_be_zero_length_ || budget <= 0) {
2224 bm->SetRest(offset); 2252 bm->SetRest(offset);
2225 SaveBMInfo(bm, not_at_start, offset); 2253 SaveBMInfo(bm, not_at_start, offset);
2226 return; 2254 return;
2227 } 2255 }
2228 ChoiceNode::FillInBMInfo(offset, budget - 1, bm, not_at_start); 2256 ChoiceNode::FillInBMInfo(offset, budget - 1, bm, not_at_start);
2229 SaveBMInfo(bm, not_at_start, offset); 2257 SaveBMInfo(bm, not_at_start, offset);
2230 } 2258 }
2231 2259
2232 2260
2233 void ChoiceNode::GetQuickCheckDetails(QuickCheckDetails* details, 2261 void ChoiceNode::GetQuickCheckDetails(QuickCheckDetails* details,
2234 RegExpCompiler* compiler, 2262 RegExpCompiler* compiler,
2235 int characters_filled_in, 2263 intptr_t characters_filled_in,
2236 bool not_at_start) { 2264 bool not_at_start) {
2237 not_at_start = (not_at_start || not_at_start_); 2265 not_at_start = (not_at_start || not_at_start_);
2238 int choice_count = alternatives_->length(); 2266 intptr_t choice_count = alternatives_->length();
2239 DCHECK(choice_count > 0); 2267 ASSERT(choice_count > 0);
2240 alternatives_->at(0).node()->GetQuickCheckDetails(details, 2268 (*alternatives_)[0].node()->GetQuickCheckDetails(details,
2241 compiler, 2269 compiler,
2242 characters_filled_in, 2270 characters_filled_in,
2243 not_at_start); 2271 not_at_start);
2244 for (int i = 1; i < choice_count; i++) { 2272 for (intptr_t i = 1; i < choice_count; i++) {
2245 QuickCheckDetails new_details(details->characters()); 2273 QuickCheckDetails new_details(details->characters());
2246 RegExpNode* node = alternatives_->at(i).node(); 2274 RegExpNode* node = (*alternatives_)[i].node();
2247 node->GetQuickCheckDetails(&new_details, compiler, 2275 node->GetQuickCheckDetails(&new_details, compiler,
2248 characters_filled_in, 2276 characters_filled_in,
2249 not_at_start); 2277 not_at_start);
2250 // Here we merge the quick match details of the two branches. 2278 // Here we merge the quick match details of the two branches.
2251 details->Merge(&new_details, characters_filled_in); 2279 details->Merge(&new_details, characters_filled_in);
2252 } 2280 }
2253 } 2281 }
2254 2282
2255 2283
2256 // Check for [0-9A-Z_a-z]. 2284 // Check for [0-9A-Z_a-z].
2257 static void EmitWordCheck(RegExpMacroAssembler* assembler, 2285 static void EmitWordCheck(RegExpMacroAssembler* assembler,
2258 Label* word, 2286 BlockLabel* word,
2259 Label* non_word, 2287 BlockLabel* non_word,
2260 bool fall_through_on_word) { 2288 bool fall_through_on_word) {
2261 if (assembler->CheckSpecialCharacterClass( 2289 if (assembler->CheckSpecialCharacterClass(
2262 fall_through_on_word ? 'w' : 'W', 2290 fall_through_on_word ? 'w' : 'W',
2263 fall_through_on_word ? non_word : word)) { 2291 fall_through_on_word ? non_word : word)) {
2264 // Optimized implementation available. 2292 // Optimized implementation available.
2265 return; 2293 return;
2266 } 2294 }
2267 assembler->CheckCharacterGT('z', non_word); 2295 assembler->CheckCharacterGT('z', non_word);
2268 assembler->CheckCharacterLT('0', non_word); 2296 assembler->CheckCharacterLT('0', non_word);
2269 assembler->CheckCharacterGT('a' - 1, word); 2297 assembler->CheckCharacterGT('a' - 1, word);
(...skipping 12 matching lines...) Expand all
2282 // that matches newline or the start of input). 2310 // that matches newline or the start of input).
2283 static void EmitHat(RegExpCompiler* compiler, 2311 static void EmitHat(RegExpCompiler* compiler,
2284 RegExpNode* on_success, 2312 RegExpNode* on_success,
2285 Trace* trace) { 2313 Trace* trace) {
2286 RegExpMacroAssembler* assembler = compiler->macro_assembler(); 2314 RegExpMacroAssembler* assembler = compiler->macro_assembler();
2287 // We will be loading the previous character into the current character 2315 // We will be loading the previous character into the current character
2288 // register. 2316 // register.
2289 Trace new_trace(*trace); 2317 Trace new_trace(*trace);
2290 new_trace.InvalidateCurrentCharacter(); 2318 new_trace.InvalidateCurrentCharacter();
2291 2319
2292 Label ok; 2320 BlockLabel ok;
2293 if (new_trace.cp_offset() == 0) { 2321 if (new_trace.cp_offset() == 0) {
2294 // The start of input counts as a newline in this context, so skip to 2322 // The start of input counts as a newline in this context, so skip to
2295 // ok if we are at the start. 2323 // ok if we are at the start.
2296 assembler->CheckAtStart(&ok); 2324 assembler->CheckAtStart(&ok);
2297 } 2325 }
2298 // We already checked that we are not at the start of input so it must be 2326 // We already checked that we are not at the start of input so it must be
2299 // OK to load the previous character. 2327 // OK to load the previous character.
2300 assembler->LoadCurrentCharacter(new_trace.cp_offset() -1, 2328 assembler->LoadCurrentCharacter(new_trace.cp_offset() -1,
2301 new_trace.backtrack(), 2329 new_trace.backtrack(),
2302 false); 2330 false);
2303 if (!assembler->CheckSpecialCharacterClass('n', 2331 if (!assembler->CheckSpecialCharacterClass('n',
2304 new_trace.backtrack())) { 2332 new_trace.backtrack())) {
2305 // Newline means \n, \r, 0x2028 or 0x2029. 2333 // Newline means \n, \r, 0x2028 or 0x2029.
2306 if (!compiler->one_byte()) { 2334 if (!compiler->one_byte()) {
2307 assembler->CheckCharacterAfterAnd(0x2028, 0xfffe, &ok); 2335 assembler->CheckCharacterAfterAnd(0x2028, 0xfffe, &ok);
2308 } 2336 }
2309 assembler->CheckCharacter('\n', &ok); 2337 assembler->CheckCharacter('\n', &ok);
2310 assembler->CheckNotCharacter('\r', new_trace.backtrack()); 2338 assembler->CheckNotCharacter('\r', new_trace.backtrack());
2311 } 2339 }
2312 assembler->Bind(&ok); 2340 assembler->BindBlock(&ok);
2313 on_success->Emit(compiler, &new_trace); 2341 on_success->Emit(compiler, &new_trace);
2314 } 2342 }
2315 2343
2316 2344
2317 // Emit the code to handle \b and \B (word-boundary or non-word-boundary). 2345 // Emit the code to handle \b and \B (word-boundary or non-word-boundary).
2318 void AssertionNode::EmitBoundaryCheck(RegExpCompiler* compiler, Trace* trace) { 2346 void AssertionNode::EmitBoundaryCheck(RegExpCompiler* compiler, Trace* trace) {
2319 RegExpMacroAssembler* assembler = compiler->macro_assembler(); 2347 RegExpMacroAssembler* assembler = compiler->macro_assembler();
2320 Trace::TriBool next_is_word_character = Trace::UNKNOWN; 2348 Trace::TriBool next_is_word_character = Trace::UNKNOWN;
2321 bool not_at_start = (trace->at_start() == Trace::FALSE_VALUE); 2349 bool not_at_start = (trace->at_start() == Trace::FALSE_VALUE);
2322 BoyerMooreLookahead* lookahead = bm_info(not_at_start); 2350 BoyerMooreLookahead* lookahead = bm_info(not_at_start);
2323 if (lookahead == NULL) { 2351 if (lookahead == NULL) {
2324 int eats_at_least = 2352 intptr_t eats_at_least =
2325 Min(kMaxLookaheadForBoyerMoore, EatsAtLeast(kMaxLookaheadForBoyerMoore, 2353 Utils::Minimum(kMaxLookaheadForBoyerMoore,
2326 kRecursionBudget, 2354 EatsAtLeast(kMaxLookaheadForBoyerMoore,
2327 not_at_start)); 2355 kRecursionBudget,
2356 not_at_start));
2328 if (eats_at_least >= 1) { 2357 if (eats_at_least >= 1) {
2329 BoyerMooreLookahead* bm = 2358 BoyerMooreLookahead* bm =
2330 new(zone()) BoyerMooreLookahead(eats_at_least, compiler, zone()); 2359 new(I) BoyerMooreLookahead(eats_at_least, compiler, I);
2331 FillInBMInfo(0, kRecursionBudget, bm, not_at_start); 2360 FillInBMInfo(0, kRecursionBudget, bm, not_at_start);
2332 if (bm->at(0)->is_non_word()) 2361 if (bm->at(0)->is_non_word())
2333 next_is_word_character = Trace::FALSE_VALUE; 2362 next_is_word_character = Trace::FALSE_VALUE;
2334 if (bm->at(0)->is_word()) next_is_word_character = Trace::TRUE_VALUE; 2363 if (bm->at(0)->is_word()) next_is_word_character = Trace::TRUE_VALUE;
2335 } 2364 }
2336 } else { 2365 } else {
2337 if (lookahead->at(0)->is_non_word()) 2366 if (lookahead->at(0)->is_non_word())
2338 next_is_word_character = Trace::FALSE_VALUE; 2367 next_is_word_character = Trace::FALSE_VALUE;
2339 if (lookahead->at(0)->is_word()) 2368 if (lookahead->at(0)->is_word())
2340 next_is_word_character = Trace::TRUE_VALUE; 2369 next_is_word_character = Trace::TRUE_VALUE;
2341 } 2370 }
2342 bool at_boundary = (assertion_type_ == AssertionNode::AT_BOUNDARY); 2371 bool at_boundary = (assertion_type_ == AssertionNode::AT_BOUNDARY);
2343 if (next_is_word_character == Trace::UNKNOWN) { 2372 if (next_is_word_character == Trace::UNKNOWN) {
2344 Label before_non_word; 2373 BlockLabel before_non_word;
2345 Label before_word; 2374 BlockLabel before_word;
2346 if (trace->characters_preloaded() != 1) { 2375 if (trace->characters_preloaded() != 1) {
2347 assembler->LoadCurrentCharacter(trace->cp_offset(), &before_non_word); 2376 assembler->LoadCurrentCharacter(trace->cp_offset(), &before_non_word);
2348 } 2377 }
2349 // Fall through on non-word. 2378 // Fall through on non-word.
2350 EmitWordCheck(assembler, &before_word, &before_non_word, false); 2379 EmitWordCheck(assembler, &before_word, &before_non_word, false);
2351 // Next character is not a word character. 2380 // Next character is not a word character.
2352 assembler->Bind(&before_non_word); 2381 assembler->BindBlock(&before_non_word);
2353 Label ok; 2382 BlockLabel ok;
2383 // Backtrack on \B (non-boundary check) if previous is a word,
2384 // since we know next *is not* a word and this would be a boundary.
2354 BacktrackIfPrevious(compiler, trace, at_boundary ? kIsNonWord : kIsWord); 2385 BacktrackIfPrevious(compiler, trace, at_boundary ? kIsNonWord : kIsWord);
2355 assembler->GoTo(&ok);
2356 2386
2357 assembler->Bind(&before_word); 2387 if (!assembler->IsClosed()) {
2388 assembler->GoTo(&ok);
2389 }
2390
2391 assembler->BindBlock(&before_word);
2358 BacktrackIfPrevious(compiler, trace, at_boundary ? kIsWord : kIsNonWord); 2392 BacktrackIfPrevious(compiler, trace, at_boundary ? kIsWord : kIsNonWord);
2359 assembler->Bind(&ok); 2393 assembler->BindBlock(&ok);
2360 } else if (next_is_word_character == Trace::TRUE_VALUE) { 2394 } else if (next_is_word_character == Trace::TRUE_VALUE) {
2361 BacktrackIfPrevious(compiler, trace, at_boundary ? kIsWord : kIsNonWord); 2395 BacktrackIfPrevious(compiler, trace, at_boundary ? kIsWord : kIsNonWord);
2362 } else { 2396 } else {
2363 DCHECK(next_is_word_character == Trace::FALSE_VALUE); 2397 ASSERT(next_is_word_character == Trace::FALSE_VALUE);
2364 BacktrackIfPrevious(compiler, trace, at_boundary ? kIsNonWord : kIsWord); 2398 BacktrackIfPrevious(compiler, trace, at_boundary ? kIsNonWord : kIsWord);
2365 } 2399 }
2366 } 2400 }
2367 2401
2368 2402
2369 void AssertionNode::BacktrackIfPrevious( 2403 void AssertionNode::BacktrackIfPrevious(
2370 RegExpCompiler* compiler, 2404 RegExpCompiler* compiler,
2371 Trace* trace, 2405 Trace* trace,
2372 AssertionNode::IfPrevious backtrack_if_previous) { 2406 AssertionNode::IfPrevious backtrack_if_previous) {
2373 RegExpMacroAssembler* assembler = compiler->macro_assembler(); 2407 RegExpMacroAssembler* assembler = compiler->macro_assembler();
2374 Trace new_trace(*trace); 2408 Trace new_trace(*trace);
2375 new_trace.InvalidateCurrentCharacter(); 2409 new_trace.InvalidateCurrentCharacter();
2376 2410
2377 Label fall_through, dummy; 2411 BlockLabel fall_through, dummy;
2378 2412
2379 Label* non_word = backtrack_if_previous == kIsNonWord ? 2413 BlockLabel* non_word = backtrack_if_previous == kIsNonWord ?
2380 new_trace.backtrack() : 2414 new_trace.backtrack() :
2381 &fall_through; 2415 &fall_through;
2382 Label* word = backtrack_if_previous == kIsNonWord ? 2416 BlockLabel* word = backtrack_if_previous == kIsNonWord ?
2383 &fall_through : 2417 &fall_through :
2384 new_trace.backtrack(); 2418 new_trace.backtrack();
2385 2419
2386 if (new_trace.cp_offset() == 0) { 2420 if (new_trace.cp_offset() == 0) {
2387 // The start of input counts as a non-word character, so the question is 2421 // The start of input counts as a non-word character, so the question is
2388 // decided if we are at the start. 2422 // decided if we are at the start.
2389 assembler->CheckAtStart(non_word); 2423 assembler->CheckAtStart(non_word);
2390 } 2424 }
2391 // We already checked that we are not at the start of input so it must be 2425 // We already checked that we are not at the start of input so it must be
2392 // OK to load the previous character. 2426 // OK to load the previous character.
2393 assembler->LoadCurrentCharacter(new_trace.cp_offset() - 1, &dummy, false); 2427 assembler->LoadCurrentCharacter(new_trace.cp_offset() - 1, &dummy, false);
2394 EmitWordCheck(assembler, word, non_word, backtrack_if_previous == kIsNonWord); 2428 EmitWordCheck(assembler, word, non_word, backtrack_if_previous == kIsNonWord);
2395 2429
2396 assembler->Bind(&fall_through); 2430 assembler->BindBlock(&fall_through);
2397 on_success()->Emit(compiler, &new_trace); 2431 on_success()->Emit(compiler, &new_trace);
2398 } 2432 }
2399 2433
2400 2434
2401 void AssertionNode::GetQuickCheckDetails(QuickCheckDetails* details, 2435 void AssertionNode::GetQuickCheckDetails(QuickCheckDetails* details,
2402 RegExpCompiler* compiler, 2436 RegExpCompiler* compiler,
2403 int filled_in, 2437 intptr_t filled_in,
2404 bool not_at_start) { 2438 bool not_at_start) {
2405 if (assertion_type_ == AT_START && not_at_start) { 2439 if (assertion_type_ == AT_START && not_at_start) {
2406 details->set_cannot_match(); 2440 details->set_cannot_match();
2407 return; 2441 return;
2408 } 2442 }
2409 return on_success()->GetQuickCheckDetails(details, 2443 return on_success()->GetQuickCheckDetails(details,
2410 compiler, 2444 compiler,
2411 filled_in, 2445 filled_in,
2412 not_at_start); 2446 not_at_start);
2413 } 2447 }
2414 2448
2415 2449
2416 void AssertionNode::Emit(RegExpCompiler* compiler, Trace* trace) { 2450 void AssertionNode::Emit(RegExpCompiler* compiler, Trace* trace) {
2417 RegExpMacroAssembler* assembler = compiler->macro_assembler(); 2451 RegExpMacroAssembler* assembler = compiler->macro_assembler();
2418 switch (assertion_type_) { 2452 switch (assertion_type_) {
2419 case AT_END: { 2453 case AT_END: {
2420 Label ok; 2454 BlockLabel ok;
2421 assembler->CheckPosition(trace->cp_offset(), &ok); 2455 assembler->CheckPosition(trace->cp_offset(), &ok);
2422 assembler->GoTo(trace->backtrack()); 2456 assembler->GoTo(trace->backtrack());
2423 assembler->Bind(&ok); 2457 assembler->BindBlock(&ok);
2424 break; 2458 break;
2425 } 2459 }
2426 case AT_START: { 2460 case AT_START: {
2427 if (trace->at_start() == Trace::FALSE_VALUE) { 2461 if (trace->at_start() == Trace::FALSE_VALUE) {
2428 assembler->GoTo(trace->backtrack()); 2462 assembler->GoTo(trace->backtrack());
2429 return; 2463 return;
2430 } 2464 }
2431 if (trace->at_start() == Trace::UNKNOWN) { 2465 if (trace->at_start() == Trace::UNKNOWN) {
2432 assembler->CheckNotAtStart(trace->backtrack()); 2466 assembler->CheckNotAtStart(trace->backtrack());
2433 Trace at_start_trace = *trace; 2467 Trace at_start_trace = *trace;
2434 at_start_trace.set_at_start(true); 2468 at_start_trace.set_at_start(true);
2435 on_success()->Emit(compiler, &at_start_trace); 2469 on_success()->Emit(compiler, &at_start_trace);
2436 return; 2470 return;
2437 } 2471 }
2438 } 2472 }
2439 break; 2473 break;
2440 case AFTER_NEWLINE: 2474 case AFTER_NEWLINE:
2441 EmitHat(compiler, on_success(), trace); 2475 EmitHat(compiler, on_success(), trace);
2442 return; 2476 return;
2443 case AT_BOUNDARY: 2477 case AT_BOUNDARY:
2444 case AT_NON_BOUNDARY: { 2478 case AT_NON_BOUNDARY: {
2445 EmitBoundaryCheck(compiler, trace); 2479 EmitBoundaryCheck(compiler, trace);
2446 return; 2480 return;
2447 } 2481 }
2448 } 2482 }
2449 on_success()->Emit(compiler, trace); 2483 on_success()->Emit(compiler, trace);
2450 } 2484 }
2451 2485
2452 2486
2453 static bool DeterminedAlready(QuickCheckDetails* quick_check, int offset) { 2487 static bool DeterminedAlready(QuickCheckDetails* quick_check, intptr_t offset) {
2454 if (quick_check == NULL) return false; 2488 if (quick_check == NULL) return false;
2455 if (offset >= quick_check->characters()) return false; 2489 if (offset >= quick_check->characters()) return false;
2456 return quick_check->positions(offset)->determines_perfectly; 2490 return quick_check->positions(offset)->determines_perfectly;
2457 } 2491 }
2458 2492
2459 2493
2460 static void UpdateBoundsCheck(int index, int* checked_up_to) { 2494 static void UpdateBoundsCheck(intptr_t index, intptr_t* checked_up_to) {
2461 if (index > *checked_up_to) { 2495 if (index > *checked_up_to) {
2462 *checked_up_to = index; 2496 *checked_up_to = index;
2463 } 2497 }
2464 } 2498 }
2465 2499
2466 2500
2467 // We call this repeatedly to generate code for each pass over the text node. 2501 // We call this repeatedly to generate code for each pass over the text node.
2468 // The passes are in increasing order of difficulty because we hope one 2502 // The passes are in increasing order of difficulty because we hope one
2469 // of the first passes will fail in which case we are saved the work of the 2503 // of the first passes will fail in which case we are saved the work of the
2470 // later passes. for example for the case independent regexp /%[asdfghjkl]a/ 2504 // later passes. for example for the case independent regexp /%[asdfghjkl]a/
(...skipping 20 matching lines...) Expand all
2491 // order to get to the code we are now generating. The quick check can involve 2525 // order to get to the code we are now generating. The quick check can involve
2492 // loading characters, which means we do not need to recheck the bounds 2526 // loading characters, which means we do not need to recheck the bounds
2493 // up to the limit the quick check already checked. In addition the quick 2527 // up to the limit the quick check already checked. In addition the quick
2494 // check can have involved a mask and compare operation which may simplify 2528 // check can have involved a mask and compare operation which may simplify
2495 // or obviate the need for further checks at some character positions. 2529 // or obviate the need for further checks at some character positions.
2496 void TextNode::TextEmitPass(RegExpCompiler* compiler, 2530 void TextNode::TextEmitPass(RegExpCompiler* compiler,
2497 TextEmitPassType pass, 2531 TextEmitPassType pass,
2498 bool preloaded, 2532 bool preloaded,
2499 Trace* trace, 2533 Trace* trace,
2500 bool first_element_checked, 2534 bool first_element_checked,
2501 int* checked_up_to) { 2535 intptr_t* checked_up_to) {
2502 RegExpMacroAssembler* assembler = compiler->macro_assembler(); 2536 RegExpMacroAssembler* assembler = compiler->macro_assembler();
2503 Isolate* isolate = assembler->zone()->isolate();
2504 bool one_byte = compiler->one_byte(); 2537 bool one_byte = compiler->one_byte();
2505 Label* backtrack = trace->backtrack(); 2538 BlockLabel* backtrack = trace->backtrack();
2506 QuickCheckDetails* quick_check = trace->quick_check_performed(); 2539 QuickCheckDetails* quick_check = trace->quick_check_performed();
2507 int element_count = elms_->length(); 2540 intptr_t element_count = elms_->length();
2508 for (int i = preloaded ? 0 : element_count - 1; i >= 0; i--) { 2541 for (intptr_t i = preloaded ? 0 : element_count - 1; i >= 0; i--) {
2509 TextElement elm = elms_->at(i); 2542 TextElement elm = elms_->At(i);
2510 int cp_offset = trace->cp_offset() + elm.cp_offset(); 2543 intptr_t cp_offset = trace->cp_offset() + elm.cp_offset();
2511 if (elm.text_type() == TextElement::ATOM) { 2544 if (elm.text_type() == TextElement::ATOM) {
2512 Vector<const uc16> quarks = elm.atom()->data(); 2545 ZoneGrowableArray<uint16_t>* quarks = elm.atom()->data();
2513 for (int j = preloaded ? 0 : quarks.length() - 1; j >= 0; j--) { 2546 for (intptr_t j = preloaded ? 0 : quarks->length() - 1; j >= 0; j--) {
2514 if (first_element_checked && i == 0 && j == 0) continue; 2547 if (first_element_checked && i == 0 && j == 0) continue;
2515 if (DeterminedAlready(quick_check, elm.cp_offset() + j)) continue; 2548 if (DeterminedAlready(quick_check, elm.cp_offset() + j)) continue;
2516 EmitCharacterFunction* emit_function = NULL; 2549 EmitCharacterFunction* emit_function = NULL;
2517 switch (pass) { 2550 switch (pass) {
2518 case NON_LATIN1_MATCH: 2551 case NON_LATIN1_MATCH:
2519 DCHECK(one_byte); 2552 ASSERT(one_byte);
2520 if (quarks[j] > String::kMaxOneByteCharCode) { 2553 if (quarks->At(j) > Symbols::kMaxOneCharCodeSymbol) {
2521 assembler->GoTo(backtrack); 2554 assembler->GoTo(backtrack);
2522 return; 2555 return;
2523 } 2556 }
2524 break; 2557 break;
2525 case NON_LETTER_CHARACTER_MATCH: 2558 case NON_LETTER_CHARACTER_MATCH:
2526 emit_function = &EmitAtomNonLetter; 2559 emit_function = &EmitAtomNonLetter;
2527 break; 2560 break;
2528 case SIMPLE_CHARACTER_MATCH: 2561 case SIMPLE_CHARACTER_MATCH:
2529 emit_function = &EmitSimpleCharacter; 2562 emit_function = &EmitSimpleCharacter;
2530 break; 2563 break;
2531 case CASE_CHARACTER_MATCH: 2564 case CASE_CHARACTER_MATCH:
2532 emit_function = &EmitAtomLetter; 2565 emit_function = &EmitAtomLetter;
2533 break; 2566 break;
2534 default: 2567 default:
2535 break; 2568 break;
2536 } 2569 }
2537 if (emit_function != NULL) { 2570 if (emit_function != NULL) {
2538 bool bound_checked = emit_function(isolate, 2571 bool bound_checked = emit_function(I,
2539 compiler, 2572 compiler,
2540 quarks[j], 2573 quarks->At(j),
2541 backtrack, 2574 backtrack,
2542 cp_offset + j, 2575 cp_offset + j,
2543 *checked_up_to < cp_offset + j, 2576 *checked_up_to < cp_offset + j,
2544 preloaded); 2577 preloaded);
2545 if (bound_checked) UpdateBoundsCheck(cp_offset + j, checked_up_to); 2578 if (bound_checked) UpdateBoundsCheck(cp_offset + j, checked_up_to);
2546 } 2579 }
2547 } 2580 }
2548 } else { 2581 } else {
2549 DCHECK_EQ(TextElement::CHAR_CLASS, elm.text_type()); 2582 ASSERT(elm.text_type() == TextElement::CHAR_CLASS);
2550 if (pass == CHARACTER_CLASS_MATCH) { 2583 if (pass == CHARACTER_CLASS_MATCH) {
2551 if (first_element_checked && i == 0) continue; 2584 if (first_element_checked && i == 0) continue;
2552 if (DeterminedAlready(quick_check, elm.cp_offset())) continue; 2585 if (DeterminedAlready(quick_check, elm.cp_offset())) continue;
2553 RegExpCharacterClass* cc = elm.char_class(); 2586 RegExpCharacterClass* cc = elm.char_class();
2554 EmitCharClass(assembler, cc, one_byte, backtrack, cp_offset, 2587 EmitCharClass(assembler,
2555 *checked_up_to < cp_offset, preloaded, zone()); 2588 cc,
2589 one_byte,
2590 backtrack,
2591 cp_offset,
2592 *checked_up_to < cp_offset,
2593 preloaded,
2594 I);
2556 UpdateBoundsCheck(cp_offset, checked_up_to); 2595 UpdateBoundsCheck(cp_offset, checked_up_to);
2557 } 2596 }
2558 } 2597 }
2559 } 2598 }
2560 } 2599 }
2561 2600
2562 2601
2563 int TextNode::Length() { 2602 intptr_t TextNode::Length() {
2564 TextElement elm = elms_->last(); 2603 TextElement elm = elms_->Last();
2565 DCHECK(elm.cp_offset() >= 0); 2604 ASSERT(elm.cp_offset() >= 0);
2566 return elm.cp_offset() + elm.length(); 2605 return elm.cp_offset() + elm.length();
2567 } 2606 }
2568 2607
2569 2608
2570 bool TextNode::SkipPass(int int_pass, bool ignore_case) { 2609 bool TextNode::SkipPass(intptr_t intptr_t_pass, bool ignore_case) {
2571 TextEmitPassType pass = static_cast<TextEmitPassType>(int_pass); 2610 TextEmitPassType pass = static_cast<TextEmitPassType>(intptr_t_pass);
2572 if (ignore_case) { 2611 if (ignore_case) {
2573 return pass == SIMPLE_CHARACTER_MATCH; 2612 return pass == SIMPLE_CHARACTER_MATCH;
2574 } else { 2613 } else {
2575 return pass == NON_LETTER_CHARACTER_MATCH || pass == CASE_CHARACTER_MATCH; 2614 return pass == NON_LETTER_CHARACTER_MATCH || pass == CASE_CHARACTER_MATCH;
2576 } 2615 }
2577 } 2616 }
2578 2617
2579 2618
2580 // This generates the code to match a text node. A text node can contain 2619 // This generates the code to match a text node. A text node can contain
2581 // straight character sequences (possibly to be matched in a case-independent 2620 // straight character sequences (possibly to be matched in a case-independent
2582 // way) and character classes. For efficiency we do not do this in a single 2621 // way) and character classes. For efficiency we do not do this in a single
2583 // pass from left to right. Instead we pass over the text node several times, 2622 // pass from left to right. Instead we pass over the text node several times,
2584 // emitting code for some character positions every time. See the comment on 2623 // emitting code for some character positions every time. See the comment on
2585 // TextEmitPass for details. 2624 // TextEmitPass for details.
2586 void TextNode::Emit(RegExpCompiler* compiler, Trace* trace) { 2625 void TextNode::Emit(RegExpCompiler* compiler, Trace* trace) {
2587 LimitResult limit_result = LimitVersions(compiler, trace); 2626 LimitResult limit_result = LimitVersions(compiler, trace);
2588 if (limit_result == DONE) return; 2627 if (limit_result == DONE) return;
2589 DCHECK(limit_result == CONTINUE); 2628 ASSERT(limit_result == CONTINUE);
2590 2629
2591 if (trace->cp_offset() + Length() > RegExpMacroAssembler::kMaxCPOffset) { 2630 if (trace->cp_offset() + Length() > RegExpMacroAssembler::kMaxCPOffset) {
2592 compiler->SetRegExpTooBig(); 2631 compiler->SetRegExpTooBig();
2593 return; 2632 return;
2594 } 2633 }
2595 2634
2596 if (compiler->one_byte()) { 2635 if (compiler->one_byte()) {
2597 int dummy = 0; 2636 intptr_t dummy = 0;
2598 TextEmitPass(compiler, NON_LATIN1_MATCH, false, trace, false, &dummy); 2637 TextEmitPass(compiler, NON_LATIN1_MATCH, false, trace, false, &dummy);
2599 } 2638 }
2600 2639
2601 bool first_elt_done = false; 2640 bool first_elt_done = false;
2602 int bound_checked_to = trace->cp_offset() - 1; 2641 intptr_t bound_checked_to = trace->cp_offset() - 1;
2603 bound_checked_to += trace->bound_checked_up_to(); 2642 bound_checked_to += trace->bound_checked_up_to();
2604 2643
2605 // If a character is preloaded into the current character register then 2644 // If a character is preloaded into the current character register then
2606 // check that now. 2645 // check that now.
2607 if (trace->characters_preloaded() == 1) { 2646 if (trace->characters_preloaded() == 1) {
2608 for (int pass = kFirstRealPass; pass <= kLastPass; pass++) { 2647 for (intptr_t pass = kFirstRealPass; pass <= kLastPass; pass++) {
2609 if (!SkipPass(pass, compiler->ignore_case())) { 2648 if (!SkipPass(pass, compiler->ignore_case())) {
2610 TextEmitPass(compiler, 2649 TextEmitPass(compiler,
2611 static_cast<TextEmitPassType>(pass), 2650 static_cast<TextEmitPassType>(pass),
2612 true, 2651 true,
2613 trace, 2652 trace,
2614 false, 2653 false,
2615 &bound_checked_to); 2654 &bound_checked_to);
2616 } 2655 }
2617 } 2656 }
2618 first_elt_done = true; 2657 first_elt_done = true;
2619 } 2658 }
2620 2659
2621 for (int pass = kFirstRealPass; pass <= kLastPass; pass++) { 2660 for (intptr_t pass = kFirstRealPass; pass <= kLastPass; pass++) {
2622 if (!SkipPass(pass, compiler->ignore_case())) { 2661 if (!SkipPass(pass, compiler->ignore_case())) {
2623 TextEmitPass(compiler, 2662 TextEmitPass(compiler,
2624 static_cast<TextEmitPassType>(pass), 2663 static_cast<TextEmitPassType>(pass),
2625 false, 2664 false,
2626 trace, 2665 trace,
2627 first_elt_done, 2666 first_elt_done,
2628 &bound_checked_to); 2667 &bound_checked_to);
2629 } 2668 }
2630 } 2669 }
2631 2670
2632 Trace successor_trace(*trace); 2671 Trace successor_trace(*trace);
2633 successor_trace.set_at_start(false); 2672 successor_trace.set_at_start(false);
2634 successor_trace.AdvanceCurrentPositionInTrace(Length(), compiler); 2673 successor_trace.AdvanceCurrentPositionInTrace(Length(), compiler);
2635 RecursionCheck rc(compiler); 2674 RecursionCheck rc(compiler);
2636 on_success()->Emit(compiler, &successor_trace); 2675 on_success()->Emit(compiler, &successor_trace);
2637 } 2676 }
2638 2677
2639 2678
2640 void Trace::InvalidateCurrentCharacter() { 2679 void Trace::InvalidateCurrentCharacter() {
2641 characters_preloaded_ = 0; 2680 characters_preloaded_ = 0;
2642 } 2681 }
2643 2682
2644 2683
2645 void Trace::AdvanceCurrentPositionInTrace(int by, RegExpCompiler* compiler) { 2684 void Trace::AdvanceCurrentPositionInTrace(intptr_t by,
2646 DCHECK(by > 0); 2685 RegExpCompiler* compiler) {
2686 ASSERT(by > 0);
2647 // We don't have an instruction for shifting the current character register 2687 // We don't have an instruction for shifting the current character register
2648 // down or for using a shifted value for anything so lets just forget that 2688 // down or for using a shifted value for anything so lets just forget that
2649 // we preloaded any characters into it. 2689 // we preloaded any characters into it.
2650 characters_preloaded_ = 0; 2690 characters_preloaded_ = 0;
2651 // Adjust the offsets of the quick check performed information. This 2691 // Adjust the offsets of the quick check performed information. This
2652 // information is used to find out what we already determined about the 2692 // information is used to find out what we already determined about the
2653 // characters by means of mask and compare. 2693 // characters by means of mask and compare.
2654 quick_check_performed_.Advance(by, compiler->one_byte()); 2694 quick_check_performed_.Advance(by, compiler->one_byte());
2655 cp_offset_ += by; 2695 cp_offset_ += by;
2656 if (cp_offset_ > RegExpMacroAssembler::kMaxCPOffset) { 2696 if (cp_offset_ > RegExpMacroAssembler::kMaxCPOffset) {
2657 compiler->SetRegExpTooBig(); 2697 compiler->SetRegExpTooBig();
2658 cp_offset_ = 0; 2698 cp_offset_ = 0;
2659 } 2699 }
2660 bound_checked_up_to_ = Max(0, bound_checked_up_to_ - by); 2700 bound_checked_up_to_ = Utils::Maximum(static_cast<intptr_t>(0),
2701 bound_checked_up_to_ - by);
2661 } 2702 }
2662 2703
2663 2704
2664 void TextNode::MakeCaseIndependent(bool is_one_byte) { 2705 void TextNode::MakeCaseIndependent(bool is_one_byte) {
2665 int element_count = elms_->length(); 2706 intptr_t element_count = elms_->length();
2666 for (int i = 0; i < element_count; i++) { 2707 for (intptr_t i = 0; i < element_count; i++) {
2667 TextElement elm = elms_->at(i); 2708 TextElement elm = elms_->At(i);
2668 if (elm.text_type() == TextElement::CHAR_CLASS) { 2709 if (elm.text_type() == TextElement::CHAR_CLASS) {
2669 RegExpCharacterClass* cc = elm.char_class(); 2710 RegExpCharacterClass* cc = elm.char_class();
2670 // None of the standard character classes is different in the case 2711 // None of the standard character classes is different in the case
2671 // independent case and it slows us down if we don't know that. 2712 // independent case and it slows us down if we don't know that.
2672 if (cc->is_standard(zone())) continue; 2713 if (cc->is_standard()) continue;
2673 ZoneList<CharacterRange>* ranges = cc->ranges(zone()); 2714 ZoneGrowableArray<CharacterRange>* ranges = cc->ranges();
2674 int range_count = ranges->length(); 2715 intptr_t range_count = ranges->length();
2675 for (int j = 0; j < range_count; j++) { 2716 for (intptr_t j = 0; j < range_count; j++) {
2676 ranges->at(j).AddCaseEquivalents(ranges, is_one_byte, zone()); 2717 (*ranges)[j].AddCaseEquivalents(ranges, is_one_byte, I);
2677 } 2718 }
2678 } 2719 }
2679 } 2720 }
2680 } 2721 }
2681 2722
2682 2723
2683 int TextNode::GreedyLoopTextLength() { 2724 intptr_t TextNode::GreedyLoopTextLength() {
2684 TextElement elm = elms_->at(elms_->length() - 1); 2725 TextElement elm = elms_->At(elms_->length() - 1);
2685 return elm.cp_offset() + elm.length(); 2726 return elm.cp_offset() + elm.length();
2686 } 2727 }
2687 2728
2688 2729
2689 RegExpNode* TextNode::GetSuccessorOfOmnivorousTextNode( 2730 RegExpNode* TextNode::GetSuccessorOfOmnivorousTextNode(
2690 RegExpCompiler* compiler) { 2731 RegExpCompiler* compiler) {
2691 if (elms_->length() != 1) return NULL; 2732 if (elms_->length() != 1) return NULL;
2692 TextElement elm = elms_->at(0); 2733 TextElement elm = elms_->At(0);
2693 if (elm.text_type() != TextElement::CHAR_CLASS) return NULL; 2734 if (elm.text_type() != TextElement::CHAR_CLASS) return NULL;
2694 RegExpCharacterClass* node = elm.char_class(); 2735 RegExpCharacterClass* node = elm.char_class();
2695 ZoneList<CharacterRange>* ranges = node->ranges(zone()); 2736 ZoneGrowableArray<CharacterRange>* ranges = node->ranges();
2696 if (!CharacterRange::IsCanonical(ranges)) { 2737 if (!CharacterRange::IsCanonical(ranges)) {
2697 CharacterRange::Canonicalize(ranges); 2738 CharacterRange::Canonicalize(ranges);
2698 } 2739 }
2699 if (node->is_negated()) { 2740 if (node->is_negated()) {
2700 return ranges->length() == 0 ? on_success() : NULL; 2741 return ranges->length() == 0 ? on_success() : NULL;
2701 } 2742 }
2702 if (ranges->length() != 1) return NULL; 2743 if (ranges->length() != 1) return NULL;
2703 uint32_t max_char; 2744 uint32_t max_char;
2704 if (compiler->one_byte()) { 2745 if (compiler->one_byte()) {
2705 max_char = String::kMaxOneByteCharCode; 2746 max_char = Symbols::kMaxOneCharCodeSymbol;
2706 } else { 2747 } else {
2707 max_char = String::kMaxUtf16CodeUnit; 2748 max_char = Utf16::kMaxCodeUnit;
2708 } 2749 }
2709 return ranges->at(0).IsEverything(max_char) ? on_success() : NULL; 2750 return ranges->At(0).IsEverything(max_char) ? on_success() : NULL;
2710 } 2751 }
2711 2752
2712 2753
2713 // Finds the fixed match length of a sequence of nodes that goes from 2754 // Finds the fixed match length of a sequence of nodes that goes from
2714 // this alternative and back to this choice node. If there are variable 2755 // this alternative and back to this choice node. If there are variable
2715 // length nodes or other complications in the way then return a sentinel 2756 // length nodes or other complications in the way then return a sentinel
2716 // value indicating that a greedy loop cannot be constructed. 2757 // value indicating that a greedy loop cannot be constructed.
2717 int ChoiceNode::GreedyLoopTextLengthForAlternative( 2758 intptr_t ChoiceNode::GreedyLoopTextLengthForAlternative(
2718 GuardedAlternative* alternative) { 2759 GuardedAlternative* alternative) {
2719 int length = 0; 2760 intptr_t length = 0;
2720 RegExpNode* node = alternative->node(); 2761 RegExpNode* node = alternative->node();
2721 // Later we will generate code for all these text nodes using recursion 2762 // Later we will generate code for all these text nodes using recursion
2722 // so we have to limit the max number. 2763 // so we have to limit the max number.
2723 int recursion_depth = 0; 2764 intptr_t recursion_depth = 0;
2724 while (node != this) { 2765 while (node != this) {
2725 if (recursion_depth++ > RegExpCompiler::kMaxRecursion) { 2766 if (recursion_depth++ > RegExpCompiler::kMaxRecursion) {
2726 return kNodeIsTooComplexForGreedyLoops; 2767 return kNodeIsTooComplexForGreedyLoops;
2727 } 2768 }
2728 int node_length = node->GreedyLoopTextLength(); 2769 intptr_t node_length = node->GreedyLoopTextLength();
2729 if (node_length == kNodeIsTooComplexForGreedyLoops) { 2770 if (node_length == kNodeIsTooComplexForGreedyLoops) {
2730 return kNodeIsTooComplexForGreedyLoops; 2771 return kNodeIsTooComplexForGreedyLoops;
2731 } 2772 }
2732 length += node_length; 2773 length += node_length;
2733 SeqRegExpNode* seq_node = static_cast<SeqRegExpNode*>(node); 2774 SeqRegExpNode* seq_node = static_cast<SeqRegExpNode*>(node);
2734 node = seq_node->on_success(); 2775 node = seq_node->on_success();
2735 } 2776 }
2736 return length; 2777 return length;
2737 } 2778 }
2738 2779
2739 2780
2740 void LoopChoiceNode::AddLoopAlternative(GuardedAlternative alt) { 2781 void LoopChoiceNode::AddLoopAlternative(GuardedAlternative alt) {
2741 DCHECK_EQ(loop_node_, NULL); 2782 ASSERT(loop_node_ == NULL);
2742 AddAlternative(alt); 2783 AddAlternative(alt);
2743 loop_node_ = alt.node(); 2784 loop_node_ = alt.node();
2744 } 2785 }
2745 2786
2746 2787
2747 void LoopChoiceNode::AddContinueAlternative(GuardedAlternative alt) { 2788 void LoopChoiceNode::AddContinueAlternative(GuardedAlternative alt) {
2748 DCHECK_EQ(continue_node_, NULL); 2789 ASSERT(continue_node_ == NULL);
2749 AddAlternative(alt); 2790 AddAlternative(alt);
2750 continue_node_ = alt.node(); 2791 continue_node_ = alt.node();
2751 } 2792 }
2752 2793
2753 2794
2754 void LoopChoiceNode::Emit(RegExpCompiler* compiler, Trace* trace) { 2795 void LoopChoiceNode::Emit(RegExpCompiler* compiler, Trace* trace) {
2755 RegExpMacroAssembler* macro_assembler = compiler->macro_assembler(); 2796 RegExpMacroAssembler* macro_assembler = compiler->macro_assembler();
2756 if (trace->stop_node() == this) { 2797 if (trace->stop_node() == this) {
2757 // Back edge of greedy optimized loop node graph. 2798 // Back edge of greedy optimized loop node graph.
2758 int text_length = 2799 intptr_t text_length =
2759 GreedyLoopTextLengthForAlternative(&(alternatives_->at(0))); 2800 GreedyLoopTextLengthForAlternative(&((*alternatives_)[0]));
2760 DCHECK(text_length != kNodeIsTooComplexForGreedyLoops); 2801 ASSERT(text_length != kNodeIsTooComplexForGreedyLoops);
2761 // Update the counter-based backtracking info on the stack. This is an 2802 // Update the counter-based backtracking info on the stack. This is an
2762 // optimization for greedy loops (see below). 2803 // optimization for greedy loops (see below).
2763 DCHECK(trace->cp_offset() == text_length); 2804 ASSERT(trace->cp_offset() == text_length);
2764 macro_assembler->AdvanceCurrentPosition(text_length); 2805 macro_assembler->AdvanceCurrentPosition(text_length);
2765 macro_assembler->GoTo(trace->loop_label()); 2806 macro_assembler->GoTo(trace->loop_label());
2766 return; 2807 return;
2767 } 2808 }
2768 DCHECK(trace->stop_node() == NULL); 2809 ASSERT(trace->stop_node() == NULL);
2769 if (!trace->is_trivial()) { 2810 if (!trace->is_trivial()) {
2770 trace->Flush(compiler, this); 2811 trace->Flush(compiler, this);
2771 return; 2812 return;
2772 } 2813 }
2773 ChoiceNode::Emit(compiler, trace); 2814 ChoiceNode::Emit(compiler, trace);
2774 } 2815 }
2775 2816
2776 2817
2777 int ChoiceNode::CalculatePreloadCharacters(RegExpCompiler* compiler, 2818 intptr_t ChoiceNode::CalculatePreloadCharacters(RegExpCompiler* compiler,
2778 int eats_at_least) { 2819 intptr_t eats_at_least) {
2779 int preload_characters = Min(4, eats_at_least); 2820 intptr_t preload_characters = Utils::Minimum(static_cast<intptr_t>(4),
2821 eats_at_least);
2780 if (compiler->macro_assembler()->CanReadUnaligned()) { 2822 if (compiler->macro_assembler()->CanReadUnaligned()) {
2781 bool one_byte = compiler->one_byte(); 2823 bool one_byte = compiler->one_byte();
2782 if (one_byte) { 2824 if (one_byte) {
2783 if (preload_characters > 4) preload_characters = 4; 2825 if (preload_characters > 4) preload_characters = 4;
2784 // We can't preload 3 characters because there is no machine instruction 2826 // We can't preload 3 characters because there is no machine instruction
2785 // to do that. We can't just load 4 because we could be reading 2827 // to do that. We can't just load 4 because we could be reading
2786 // beyond the end of the string, which could cause a memory fault. 2828 // beyond the end of the string, which could cause a memory fault.
2787 if (preload_characters == 3) preload_characters = 2; 2829 if (preload_characters == 3) preload_characters = 2;
2788 } else { 2830 } else {
2789 if (preload_characters > 2) preload_characters = 2; 2831 if (preload_characters > 2) preload_characters = 2;
2790 } 2832 }
2791 } else { 2833 } else {
2792 if (preload_characters > 1) preload_characters = 1; 2834 if (preload_characters > 1) preload_characters = 1;
2793 } 2835 }
2794 return preload_characters; 2836 return preload_characters;
2795 } 2837 }
2796 2838
2797 2839
2798 // This class is used when generating the alternatives in a choice node. It 2840 // This structure is used when generating the alternatives in a choice node. It
2799 // records the way the alternative is being code generated. 2841 // records the way the alternative is being code generated.
2800 class AlternativeGeneration: public Malloced { 2842 struct AlternativeGeneration {
2801 public:
2802 AlternativeGeneration() 2843 AlternativeGeneration()
2803 : possible_success(), 2844 : possible_success(),
2804 expects_preload(false), 2845 expects_preload(false),
2805 after(), 2846 after(),
2806 quick_check_details() { } 2847 quick_check_details() { }
2807 Label possible_success; 2848 BlockLabel possible_success;
2808 bool expects_preload; 2849 bool expects_preload;
2809 Label after; 2850 BlockLabel after;
2810 QuickCheckDetails quick_check_details; 2851 QuickCheckDetails quick_check_details;
2811 }; 2852 };
2812 2853
2813 2854
2814 // Creates a list of AlternativeGenerations. If the list has a reasonable 2855 // Creates a list of AlternativeGenerations. If the list has a reasonable
2815 // size then it is on the stack, otherwise the excess is on the heap. 2856 // size then it is on the stack, otherwise the excess is on the heap.
2816 class AlternativeGenerationList { 2857 class AlternativeGenerationList {
2817 public: 2858 public:
2818 AlternativeGenerationList(int count, Zone* zone) 2859 explicit AlternativeGenerationList(intptr_t count)
2819 : alt_gens_(count, zone) { 2860 : alt_gens_(count) {
2820 for (int i = 0; i < count && i < kAFew; i++) { 2861 for (intptr_t i = 0; i < count && i < kAFew; i++) {
2821 alt_gens_.Add(a_few_alt_gens_ + i, zone); 2862 alt_gens_.Add(a_few_alt_gens_ + i);
2822 } 2863 }
2823 for (int i = kAFew; i < count; i++) { 2864 for (intptr_t i = kAFew; i < count; i++) {
2824 alt_gens_.Add(new AlternativeGeneration(), zone); 2865 alt_gens_.Add(new AlternativeGeneration());
2825 } 2866 }
2826 } 2867 }
2827 ~AlternativeGenerationList() { 2868 ~AlternativeGenerationList() {
2828 for (int i = kAFew; i < alt_gens_.length(); i++) { 2869 for (intptr_t i = kAFew; i < alt_gens_.length(); i++) {
2829 delete alt_gens_[i]; 2870 delete alt_gens_[i];
2830 alt_gens_[i] = NULL; 2871 alt_gens_[i] = NULL;
2831 } 2872 }
2832 } 2873 }
2833 2874
2834 AlternativeGeneration* at(int i) { 2875 AlternativeGeneration* at(intptr_t i) {
2835 return alt_gens_[i]; 2876 return alt_gens_[i];
2836 } 2877 }
2837 2878
2838 private: 2879 private:
2839 static const int kAFew = 10; 2880 static const intptr_t kAFew = 10;
2840 ZoneList<AlternativeGeneration*> alt_gens_; 2881 GrowableArray<AlternativeGeneration*> alt_gens_;
2841 AlternativeGeneration a_few_alt_gens_[kAFew]; 2882 AlternativeGeneration a_few_alt_gens_[kAFew];
2883
2884 DISALLOW_ALLOCATION();
2842 }; 2885 };
2843 2886
2844 2887
2845 // The '2' variant is has inclusive from and exclusive to. 2888 // The '2' variant is inclusive from and exclusive to.
2846 // This covers \s as defined in ECMA-262 5.1, 15.10.2.12, 2889 // This covers \s as defined in ECMA-262 5.1, 15.10.2.12,
2847 // which include WhiteSpace (7.2) or LineTerminator (7.3) values. 2890 // which include WhiteSpace (7.2) or LineTerminator (7.3) values.
2848 static const int kSpaceRanges[] = { '\t', '\r' + 1, ' ', ' ' + 1, 2891 static const intptr_t kSpaceRanges[] = { '\t', '\r' + 1, ' ', ' ' + 1,
2849 0x00A0, 0x00A1, 0x1680, 0x1681, 0x180E, 0x180F, 0x2000, 0x200B, 2892 0x00A0, 0x00A1, 0x1680, 0x1681, 0x180E, 0x180F, 0x2000, 0x200B,
2850 0x2028, 0x202A, 0x202F, 0x2030, 0x205F, 0x2060, 0x3000, 0x3001, 2893 0x2028, 0x202A, 0x202F, 0x2030, 0x205F, 0x2060, 0x3000, 0x3001,
2851 0xFEFF, 0xFF00, 0x10000 }; 2894 0xFEFF, 0xFF00, 0x10000 };
2852 static const int kSpaceRangeCount = arraysize(kSpaceRanges); 2895 static const intptr_t kSpaceRangeCount = ARRAY_SIZE(kSpaceRanges);
2853 2896 static const intptr_t kWordRanges[] = {
2854 static const int kWordRanges[] = {
2855 '0', '9' + 1, 'A', 'Z' + 1, '_', '_' + 1, 'a', 'z' + 1, 0x10000 }; 2897 '0', '9' + 1, 'A', 'Z' + 1, '_', '_' + 1, 'a', 'z' + 1, 0x10000 };
2856 static const int kWordRangeCount = arraysize(kWordRanges); 2898 static const intptr_t kWordRangeCount = ARRAY_SIZE(kWordRanges);
2857 static const int kDigitRanges[] = { '0', '9' + 1, 0x10000 }; 2899 static const intptr_t kDigitRanges[] = { '0', '9' + 1, 0x10000 };
2858 static const int kDigitRangeCount = arraysize(kDigitRanges); 2900 static const intptr_t kDigitRangeCount = ARRAY_SIZE(kDigitRanges);
2859 static const int kSurrogateRanges[] = { 0xd800, 0xe000, 0x10000 }; 2901 static const intptr_t kSurrogateRanges[] = { 0xd800, 0xe000, 0x10000 };
2860 static const int kSurrogateRangeCount = arraysize(kSurrogateRanges); 2902 static const intptr_t kSurrogateRangeCount = ARRAY_SIZE(kSurrogateRanges);
2861 static const int kLineTerminatorRanges[] = { 0x000A, 0x000B, 0x000D, 0x000E, 2903 static const intptr_t kLineTerminatorRanges[] = {
2862 0x2028, 0x202A, 0x10000 }; 2904 0x000A, 0x000B, 0x000D, 0x000E, 0x2028, 0x202A, 0x10000 };
2863 static const int kLineTerminatorRangeCount = arraysize(kLineTerminatorRanges); 2905 static const intptr_t kLineTerminatorRangeCount =
2906 ARRAY_SIZE(kLineTerminatorRanges);
2864 2907
2865 2908
2866 void BoyerMoorePositionInfo::Set(int character) { 2909 void BoyerMoorePositionInfo::Set(intptr_t character) {
2867 SetInterval(Interval(character, character)); 2910 SetInterval(Interval(character, character));
2868 } 2911 }
2869 2912
2870 2913
2871 void BoyerMoorePositionInfo::SetInterval(const Interval& interval) { 2914 void BoyerMoorePositionInfo::SetInterval(const Interval& interval) {
2872 s_ = AddRange(s_, kSpaceRanges, kSpaceRangeCount, interval); 2915 s_ = AddRange(s_, kSpaceRanges, kSpaceRangeCount, interval);
2873 w_ = AddRange(w_, kWordRanges, kWordRangeCount, interval); 2916 w_ = AddRange(w_, kWordRanges, kWordRangeCount, interval);
2874 d_ = AddRange(d_, kDigitRanges, kDigitRangeCount, interval); 2917 d_ = AddRange(d_, kDigitRanges, kDigitRangeCount, interval);
2875 surrogate_ = 2918 surrogate_ =
2876 AddRange(surrogate_, kSurrogateRanges, kSurrogateRangeCount, interval); 2919 AddRange(surrogate_, kSurrogateRanges, kSurrogateRangeCount, interval);
2877 if (interval.to() - interval.from() >= kMapSize - 1) { 2920 if (interval.to() - interval.from() >= kMapSize - 1) {
2878 if (map_count_ != kMapSize) { 2921 if (map_count_ != kMapSize) {
2879 map_count_ = kMapSize; 2922 map_count_ = kMapSize;
2880 for (int i = 0; i < kMapSize; i++) map_->at(i) = true; 2923 for (intptr_t i = 0; i < kMapSize; i++) (*map_)[i] = true;
2881 } 2924 }
2882 return; 2925 return;
2883 } 2926 }
2884 for (int i = interval.from(); i <= interval.to(); i++) { 2927 for (intptr_t i = interval.from(); i <= interval.to(); i++) {
2885 int mod_character = (i & kMask); 2928 intptr_t mod_character = (i & kMask);
2886 if (!map_->at(mod_character)) { 2929 if (!map_->At(mod_character)) {
2887 map_count_++; 2930 map_count_++;
2888 map_->at(mod_character) = true; 2931 (*map_)[mod_character] = true;
2889 } 2932 }
2890 if (map_count_ == kMapSize) return; 2933 if (map_count_ == kMapSize) return;
2891 } 2934 }
2892 } 2935 }
2893 2936
2894 2937
2895 void BoyerMoorePositionInfo::SetAll() { 2938 void BoyerMoorePositionInfo::SetAll() {
2896 s_ = w_ = d_ = kLatticeUnknown; 2939 s_ = w_ = d_ = kLatticeUnknown;
2897 if (map_count_ != kMapSize) { 2940 if (map_count_ != kMapSize) {
2898 map_count_ = kMapSize; 2941 map_count_ = kMapSize;
2899 for (int i = 0; i < kMapSize; i++) map_->at(i) = true; 2942 for (intptr_t i = 0; i < kMapSize; i++) (*map_)[i] = true;
2900 } 2943 }
2901 } 2944 }
2902 2945
2903 2946
2904 BoyerMooreLookahead::BoyerMooreLookahead( 2947 BoyerMooreLookahead::BoyerMooreLookahead(
2905 int length, RegExpCompiler* compiler, Zone* zone) 2948 intptr_t length, RegExpCompiler* compiler, Isolate* isolate)
2906 : length_(length), 2949 : length_(length),
2907 compiler_(compiler) { 2950 compiler_(compiler) {
2908 if (compiler->one_byte()) { 2951 if (compiler->one_byte()) {
2909 max_char_ = String::kMaxOneByteCharCode; 2952 max_char_ = Symbols::kMaxOneCharCodeSymbol;
2910 } else { 2953 } else {
2911 max_char_ = String::kMaxUtf16CodeUnit; 2954 max_char_ = Utf16::kMaxCodeUnit;
2912 } 2955 }
2913 bitmaps_ = new(zone) ZoneList<BoyerMoorePositionInfo*>(length, zone); 2956 bitmaps_ = new(isolate) ZoneGrowableArray<BoyerMoorePositionInfo*>(length);
2914 for (int i = 0; i < length; i++) { 2957 for (intptr_t i = 0; i < length; i++) {
2915 bitmaps_->Add(new(zone) BoyerMoorePositionInfo(zone), zone); 2958 bitmaps_->Add(new(isolate) BoyerMoorePositionInfo(isolate));
2916 } 2959 }
2917 } 2960 }
2918 2961
2919 2962
2920 // Find the longest range of lookahead that has the fewest number of different 2963 // Find the longest range of lookahead that has the fewest number of different
2921 // characters that can occur at a given position. Since we are optimizing two 2964 // characters that can occur at a given position. Since we are optimizing two
2922 // different parameters at once this is a tradeoff. 2965 // different parameters at once this is a tradeoff.
2923 bool BoyerMooreLookahead::FindWorthwhileInterval(int* from, int* to) { 2966 bool BoyerMooreLookahead::FindWorthwhileInterval(intptr_t* from, intptr_t* to) {
2924 int biggest_points = 0; 2967 intptr_t biggest_points = 0;
2925 // If more than 32 characters out of 128 can occur it is unlikely that we can 2968 // If more than 32 characters out of 128 can occur it is unlikely that we can
2926 // be lucky enough to step forwards much of the time. 2969 // be lucky enough to step forwards much of the time.
2927 const int kMaxMax = 32; 2970 const intptr_t kMaxMax = 32;
2928 for (int max_number_of_chars = 4; 2971 for (intptr_t max_number_of_chars = 4;
2929 max_number_of_chars < kMaxMax; 2972 max_number_of_chars < kMaxMax;
2930 max_number_of_chars *= 2) { 2973 max_number_of_chars *= 2) {
2931 biggest_points = 2974 biggest_points =
2932 FindBestInterval(max_number_of_chars, biggest_points, from, to); 2975 FindBestInterval(max_number_of_chars, biggest_points, from, to);
2933 } 2976 }
2934 if (biggest_points == 0) return false; 2977 if (biggest_points == 0) return false;
2935 return true; 2978 return true;
2936 } 2979 }
2937 2980
2938 2981
2939 // Find the highest-points range between 0 and length_ where the character 2982 // Find the highest-points range between 0 and length_ where the character
2940 // information is not too vague. 'Too vague' means that there are more than 2983 // information is not too vague. 'Too vague' means that there are more than
2941 // max_number_of_chars that can occur at this position. Calculates the number 2984 // max_number_of_chars that can occur at this position. Calculates the number
2942 // of points as the product of width-of-the-range and 2985 // of points as the product of width-of-the-range and
2943 // probability-of-finding-one-of-the-characters, where the probability is 2986 // probability-of-finding-one-of-the-characters, where the probability is
2944 // calculated using the frequency distribution of the sample subject string. 2987 // calculated using the frequency distribution of the sample subject string.
2945 int BoyerMooreLookahead::FindBestInterval( 2988 intptr_t BoyerMooreLookahead::FindBestInterval(
2946 int max_number_of_chars, int old_biggest_points, int* from, int* to) { 2989 intptr_t max_number_of_chars,
2947 int biggest_points = old_biggest_points; 2990 intptr_t old_biggest_points,
2948 static const int kSize = RegExpMacroAssembler::kTableSize; 2991 intptr_t* from,
2949 for (int i = 0; i < length_; ) { 2992 intptr_t* to) {
2993 intptr_t biggest_points = old_biggest_points;
2994 static const intptr_t kSize = RegExpMacroAssembler::kTableSize;
2995 for (intptr_t i = 0; i < length_; ) {
2950 while (i < length_ && Count(i) > max_number_of_chars) i++; 2996 while (i < length_ && Count(i) > max_number_of_chars) i++;
2951 if (i == length_) break; 2997 if (i == length_) break;
2952 int remembered_from = i; 2998 intptr_t remembered_from = i;
2953 bool union_map[kSize]; 2999 bool union_map[kSize];
2954 for (int j = 0; j < kSize; j++) union_map[j] = false; 3000 for (intptr_t j = 0; j < kSize; j++) union_map[j] = false;
2955 while (i < length_ && Count(i) <= max_number_of_chars) { 3001 while (i < length_ && Count(i) <= max_number_of_chars) {
2956 BoyerMoorePositionInfo* map = bitmaps_->at(i); 3002 BoyerMoorePositionInfo* map = bitmaps_->At(i);
2957 for (int j = 0; j < kSize; j++) union_map[j] |= map->at(j); 3003 for (intptr_t j = 0; j < kSize; j++) union_map[j] |= map->at(j);
2958 i++; 3004 i++;
2959 } 3005 }
2960 int frequency = 0; 3006 intptr_t frequency = 0;
2961 for (int j = 0; j < kSize; j++) { 3007 for (intptr_t j = 0; j < kSize; j++) {
2962 if (union_map[j]) { 3008 if (union_map[j]) {
2963 // Add 1 to the frequency to give a small per-character boost for 3009 // Add 1 to the frequency to give a small per-character boost for
2964 // the cases where our sampling is not good enough and many 3010 // the cases where our sampling is not good enough and many
2965 // characters have a frequency of zero. This means the frequency 3011 // characters have a frequency of zero. This means the frequency
2966 // can theoretically be up to 2*kSize though we treat it mostly as 3012 // can theoretically be up to 2*kSize though we treat it mostly as
2967 // a fraction of kSize. 3013 // a fraction of kSize.
2968 frequency += compiler_->frequency_collator()->Frequency(j) + 1; 3014 frequency += compiler_->frequency_collator()->Frequency(j) + 1;
2969 } 3015 }
2970 } 3016 }
2971 // We use the probability of skipping times the distance we are skipping to 3017 // We use the probability of skipping times the distance we are skipping to
2972 // judge the effectiveness of this. Actually we have a cut-off: By 3018 // judge the effectiveness of this. Actually we have a cut-off: By
2973 // dividing by 2 we switch off the skipping if the probability of skipping 3019 // dividing by 2 we switch off the skipping if the probability of skipping
2974 // is less than 50%. This is because the multibyte mask-and-compare 3020 // is less than 50%. This is because the multibyte mask-and-compare
2975 // skipping in quickcheck is more likely to do well on this case. 3021 // skipping in quickcheck is more likely to do well on this case.
2976 bool in_quickcheck_range = 3022 bool in_quickcheck_range = ((i - remembered_from < 4) ||
2977 ((i - remembered_from < 4) || 3023 (compiler_->one_byte() ? remembered_from <= 4 : remembered_from <= 2));
2978 (compiler_->one_byte() ? remembered_from <= 4 : remembered_from <= 2));
2979 // Called 'probability' but it is only a rough estimate and can actually 3024 // Called 'probability' but it is only a rough estimate and can actually
2980 // be outside the 0-kSize range. 3025 // be outside the 0-kSize range.
2981 int probability = (in_quickcheck_range ? kSize / 2 : kSize) - frequency; 3026 intptr_t probability =
2982 int points = (i - remembered_from) * probability; 3027 (in_quickcheck_range ? kSize / 2 : kSize) - frequency;
3028 intptr_t points = (i - remembered_from) * probability;
2983 if (points > biggest_points) { 3029 if (points > biggest_points) {
2984 *from = remembered_from; 3030 *from = remembered_from;
2985 *to = i - 1; 3031 *to = i - 1;
2986 biggest_points = points; 3032 biggest_points = points;
2987 } 3033 }
2988 } 3034 }
2989 return biggest_points; 3035 return biggest_points;
2990 } 3036 }
2991 3037
2992 3038
2993 // Take all the characters that will not prevent a successful match if they 3039 // Take all the characters that will not prevent a successful match if they
2994 // occur in the subject string in the range between min_lookahead and 3040 // occur in the subject string in the range between min_lookahead and
2995 // max_lookahead (inclusive) measured from the current position. If the 3041 // max_lookahead (inclusive) measured from the current position. If the
2996 // character at max_lookahead offset is not one of these characters, then we 3042 // character at max_lookahead offset is not one of these characters, then we
2997 // can safely skip forwards by the number of characters in the range. 3043 // can safely skip forwards by the number of characters in the range.
2998 int BoyerMooreLookahead::GetSkipTable(int min_lookahead, 3044 intptr_t BoyerMooreLookahead::GetSkipTable(
2999 int max_lookahead, 3045 intptr_t min_lookahead,
3000 Handle<ByteArray> boolean_skip_table) { 3046 intptr_t max_lookahead,
3001 const int kSize = RegExpMacroAssembler::kTableSize; 3047 const TypedData& boolean_skip_table) {
3048 const intptr_t kSize = RegExpMacroAssembler::kTableSize;
3002 3049
3003 const int kSkipArrayEntry = 0; 3050 const intptr_t kSkipArrayEntry = 0;
3004 const int kDontSkipArrayEntry = 1; 3051 const intptr_t kDontSkipArrayEntry = 1;
3005 3052
3006 for (int i = 0; i < kSize; i++) { 3053 for (intptr_t i = 0; i < kSize; i++) {
3007 boolean_skip_table->set(i, kSkipArrayEntry); 3054 boolean_skip_table.SetUint8(i, kSkipArrayEntry);
3008 } 3055 }
3009 int skip = max_lookahead + 1 - min_lookahead; 3056 intptr_t skip = max_lookahead + 1 - min_lookahead;
3010 3057
3011 for (int i = max_lookahead; i >= min_lookahead; i--) { 3058 for (intptr_t i = max_lookahead; i >= min_lookahead; i--) {
3012 BoyerMoorePositionInfo* map = bitmaps_->at(i); 3059 BoyerMoorePositionInfo* map = bitmaps_->At(i);
3013 for (int j = 0; j < kSize; j++) { 3060 for (intptr_t j = 0; j < kSize; j++) {
3014 if (map->at(j)) { 3061 if (map->at(j)) {
3015 boolean_skip_table->set(j, kDontSkipArrayEntry); 3062 boolean_skip_table.SetUint8(j, kDontSkipArrayEntry);
3016 } 3063 }
3017 } 3064 }
3018 } 3065 }
3019 3066
3020 return skip; 3067 return skip;
3021 } 3068 }
3022 3069
3023 3070
3024 // See comment above on the implementation of GetSkipTable. 3071 // See comment above on the implementation of GetSkipTable.
3025 void BoyerMooreLookahead::EmitSkipInstructions(RegExpMacroAssembler* masm) { 3072 void BoyerMooreLookahead::EmitSkipInstructions(RegExpMacroAssembler* masm) {
3026 const int kSize = RegExpMacroAssembler::kTableSize; 3073 const intptr_t kSize = RegExpMacroAssembler::kTableSize;
3027 3074
3028 int min_lookahead = 0; 3075 intptr_t min_lookahead = 0;
3029 int max_lookahead = 0; 3076 intptr_t max_lookahead = 0;
3030 3077
3031 if (!FindWorthwhileInterval(&min_lookahead, &max_lookahead)) return; 3078 if (!FindWorthwhileInterval(&min_lookahead, &max_lookahead)) return;
3032 3079
3033 bool found_single_character = false; 3080 bool found_single_character = false;
3034 int single_character = 0; 3081 intptr_t single_character = 0;
3035 for (int i = max_lookahead; i >= min_lookahead; i--) { 3082 for (intptr_t i = max_lookahead; i >= min_lookahead; i--) {
3036 BoyerMoorePositionInfo* map = bitmaps_->at(i); 3083 BoyerMoorePositionInfo* map = bitmaps_->At(i);
3037 if (map->map_count() > 1 || 3084 if (map->map_count() > 1 ||
3038 (found_single_character && map->map_count() != 0)) { 3085 (found_single_character && map->map_count() != 0)) {
3039 found_single_character = false; 3086 found_single_character = false;
3040 break; 3087 break;
3041 } 3088 }
3042 for (int j = 0; j < kSize; j++) { 3089 for (intptr_t j = 0; j < kSize; j++) {
3043 if (map->at(j)) { 3090 if (map->at(j)) {
3044 found_single_character = true; 3091 found_single_character = true;
3045 single_character = j; 3092 single_character = j;
3046 break; 3093 break;
3047 } 3094 }
3048 } 3095 }
3049 } 3096 }
3050 3097
3051 int lookahead_width = max_lookahead + 1 - min_lookahead; 3098 intptr_t lookahead_width = max_lookahead + 1 - min_lookahead;
3052 3099
3053 if (found_single_character && lookahead_width == 1 && max_lookahead < 3) { 3100 if (found_single_character && lookahead_width == 1 && max_lookahead < 3) {
3054 // The mask-compare can probably handle this better. 3101 // The mask-compare can probably handle this better.
3055 return; 3102 return;
3056 } 3103 }
3057 3104
3058 if (found_single_character) { 3105 if (found_single_character) {
3059 Label cont, again; 3106 BlockLabel cont, again;
3060 masm->Bind(&again); 3107 masm->BindBlock(&again);
3061 masm->LoadCurrentCharacter(max_lookahead, &cont, true); 3108 masm->LoadCurrentCharacter(max_lookahead, &cont, true);
3062 if (max_char_ > kSize) { 3109 if (max_char_ > kSize) {
3063 masm->CheckCharacterAfterAnd(single_character, 3110 masm->CheckCharacterAfterAnd(single_character,
3064 RegExpMacroAssembler::kTableMask, 3111 RegExpMacroAssembler::kTableMask,
3065 &cont); 3112 &cont);
3066 } else { 3113 } else {
3067 masm->CheckCharacter(single_character, &cont); 3114 masm->CheckCharacter(single_character, &cont);
3068 } 3115 }
3069 masm->AdvanceCurrentPosition(lookahead_width); 3116 masm->AdvanceCurrentPosition(lookahead_width);
3070 masm->GoTo(&again); 3117 masm->GoTo(&again);
3071 masm->Bind(&cont); 3118 masm->BindBlock(&cont);
3072 return; 3119 return;
3073 } 3120 }
3074 3121
3075 Factory* factory = masm->zone()->isolate()->factory(); 3122 const TypedData& boolean_skip_table = TypedData::ZoneHandle(
3076 Handle<ByteArray> boolean_skip_table = factory->NewByteArray(kSize, TENURED); 3123 compiler_->isolate(),
3077 int skip_distance = GetSkipTable( 3124 TypedData::New(kTypedDataUint8ArrayCid, kSize, Heap::kOld));
3125 intptr_t skip_distance = GetSkipTable(
3078 min_lookahead, max_lookahead, boolean_skip_table); 3126 min_lookahead, max_lookahead, boolean_skip_table);
3079 DCHECK(skip_distance != 0); 3127 ASSERT(skip_distance != 0);
3080 3128
3081 Label cont, again; 3129 BlockLabel cont, again;
3082 masm->Bind(&again); 3130
3131 masm->BindBlock(&again);
3083 masm->LoadCurrentCharacter(max_lookahead, &cont, true); 3132 masm->LoadCurrentCharacter(max_lookahead, &cont, true);
3084 masm->CheckBitInTable(boolean_skip_table, &cont); 3133 masm->CheckBitInTable(boolean_skip_table, &cont);
3085 masm->AdvanceCurrentPosition(skip_distance); 3134 masm->AdvanceCurrentPosition(skip_distance);
3086 masm->GoTo(&again); 3135 masm->GoTo(&again);
3087 masm->Bind(&cont); 3136 masm->BindBlock(&cont);
3137
3138 return;
3088 } 3139 }
3089 3140
3090 3141
3091 /* Code generation for choice nodes. 3142 /* Code generation for choice nodes.
3092 * 3143 *
3093 * We generate quick checks that do a mask and compare to eliminate a 3144 * We generate quick checks that do a mask and compare to eliminate a
3094 * choice. If the quick check succeeds then it jumps to the continuation to 3145 * choice. If the quick check succeeds then it jumps to the continuation to
3095 * do slow checks and check subsequent nodes. If it fails (the common case) 3146 * do slow checks and check subsequent nodes. If it fails (the common case)
3096 * it falls through to the next choice. 3147 * it falls through to the next choice.
3097 * 3148 *
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
3163 */ 3214 */
3164 3215
3165 GreedyLoopState::GreedyLoopState(bool not_at_start) { 3216 GreedyLoopState::GreedyLoopState(bool not_at_start) {
3166 counter_backtrack_trace_.set_backtrack(&label_); 3217 counter_backtrack_trace_.set_backtrack(&label_);
3167 if (not_at_start) counter_backtrack_trace_.set_at_start(false); 3218 if (not_at_start) counter_backtrack_trace_.set_at_start(false);
3168 } 3219 }
3169 3220
3170 3221
3171 void ChoiceNode::AssertGuardsMentionRegisters(Trace* trace) { 3222 void ChoiceNode::AssertGuardsMentionRegisters(Trace* trace) {
3172 #ifdef DEBUG 3223 #ifdef DEBUG
3173 int choice_count = alternatives_->length(); 3224 intptr_t choice_count = alternatives_->length();
3174 for (int i = 0; i < choice_count - 1; i++) { 3225 for (intptr_t i = 0; i < choice_count - 1; i++) {
3175 GuardedAlternative alternative = alternatives_->at(i); 3226 GuardedAlternative alternative = alternatives_->At(i);
3176 ZoneList<Guard*>* guards = alternative.guards(); 3227 ZoneGrowableArray<Guard*>* guards = alternative.guards();
3177 int guard_count = (guards == NULL) ? 0 : guards->length(); 3228 intptr_t guard_count = (guards == NULL) ? 0 : guards->length();
3178 for (int j = 0; j < guard_count; j++) { 3229 for (intptr_t j = 0; j < guard_count; j++) {
3179 DCHECK(!trace->mentions_reg(guards->at(j)->reg())); 3230 ASSERT(!trace->mentions_reg(guards->At(j)->reg()));
3180 } 3231 }
3181 } 3232 }
3182 #endif 3233 #endif
3183 } 3234 }
3184 3235
3185 3236
3186 void ChoiceNode::SetUpPreLoad(RegExpCompiler* compiler, 3237 void ChoiceNode::SetUpPreLoad(RegExpCompiler* compiler,
3187 Trace* current_trace, 3238 Trace* current_trace,
3188 PreloadState* state) { 3239 PreloadState* state) {
3189 if (state->eats_at_least_ == PreloadState::kEatsAtLeastNotYetInitialized) { 3240 if (state->eats_at_least_ == PreloadState::kEatsAtLeastNotYetInitialized) {
3190 // Save some time by looking at most one machine word ahead. 3241 // Save some time by looking at most one machine word ahead.
3191 state->eats_at_least_ = 3242 state->eats_at_least_ =
3192 EatsAtLeast(compiler->one_byte() ? 4 : 2, kRecursionBudget, 3243 EatsAtLeast(compiler->one_byte() ? 4 : 2, kRecursionBudget,
3193 current_trace->at_start() == Trace::FALSE_VALUE); 3244 current_trace->at_start() == Trace::FALSE_VALUE);
3194 } 3245 }
3195 state->preload_characters_ = 3246 state->preload_characters_ =
3196 CalculatePreloadCharacters(compiler, state->eats_at_least_); 3247 CalculatePreloadCharacters(compiler, state->eats_at_least_);
3197 3248
3198 state->preload_is_current_ = 3249 state->preload_is_current_ =
3199 (current_trace->characters_preloaded() == state->preload_characters_); 3250 (current_trace->characters_preloaded() == state->preload_characters_);
3200 state->preload_has_checked_bounds_ = state->preload_is_current_; 3251 state->preload_has_checked_bounds_ = state->preload_is_current_;
3201 } 3252 }
3202 3253
3203 3254
3204 void ChoiceNode::Emit(RegExpCompiler* compiler, Trace* trace) { 3255 void ChoiceNode::Emit(RegExpCompiler* compiler, Trace* trace) {
3205 int choice_count = alternatives_->length(); 3256 intptr_t choice_count = alternatives_->length();
3206 3257
3207 AssertGuardsMentionRegisters(trace); 3258 AssertGuardsMentionRegisters(trace);
3208 3259
3209 LimitResult limit_result = LimitVersions(compiler, trace); 3260 LimitResult limit_result = LimitVersions(compiler, trace);
3210 if (limit_result == DONE) return; 3261 if (limit_result == DONE) return;
3211 DCHECK(limit_result == CONTINUE); 3262 ASSERT(limit_result == CONTINUE);
3212 3263
3213 // For loop nodes we already flushed (see LoopChoiceNode::Emit), but for 3264 // For loop nodes we already flushed (see LoopChoiceNode::Emit), but for
3214 // other choice nodes we only flush if we are out of code size budget. 3265 // other choice nodes we only flush if we are out of code size budget.
3215 if (trace->flush_budget() == 0 && trace->actions() != NULL) { 3266 if (trace->flush_budget() == 0 && trace->actions() != NULL) {
3216 trace->Flush(compiler, this); 3267 trace->Flush(compiler, this);
3217 return; 3268 return;
3218 } 3269 }
3219 3270
3220 RecursionCheck rc(compiler); 3271 RecursionCheck rc(compiler);
3221 3272
3222 PreloadState preload; 3273 PreloadState preload;
3223 preload.init(); 3274 preload.init();
3224 GreedyLoopState greedy_loop_state(not_at_start()); 3275 GreedyLoopState greedy_loop_state(not_at_start());
3225 3276
3226 int text_length = GreedyLoopTextLengthForAlternative(&alternatives_->at(0)); 3277 intptr_t text_length =
3227 AlternativeGenerationList alt_gens(choice_count, zone()); 3278 GreedyLoopTextLengthForAlternative(&((*alternatives_)[0]));
3279 AlternativeGenerationList alt_gens(choice_count);
3228 3280
3229 if (choice_count > 1 && text_length != kNodeIsTooComplexForGreedyLoops) { 3281 if (choice_count > 1 && text_length != kNodeIsTooComplexForGreedyLoops) {
3230 trace = EmitGreedyLoop(compiler, 3282 trace = EmitGreedyLoop(compiler,
3231 trace, 3283 trace,
3232 &alt_gens, 3284 &alt_gens,
3233 &preload, 3285 &preload,
3234 &greedy_loop_state, 3286 &greedy_loop_state,
3235 text_length); 3287 text_length);
3236 } else { 3288 } else {
3237 // TODO(erikcorry): Delete this. We don't need this label, but it makes us 3289 // TODO(erikcorry): Delete this. We don't need this label, but it makes us
3238 // match the traces produced pre-cleanup. 3290 // match the traces produced pre-cleanup.
3239 Label second_choice; 3291 BlockLabel second_choice;
3240 compiler->macro_assembler()->Bind(&second_choice); 3292 compiler->macro_assembler()->BindBlock(&second_choice);
3241 3293
3242 preload.eats_at_least_ = EmitOptimizedUnanchoredSearch(compiler, trace); 3294 preload.eats_at_least_ = EmitOptimizedUnanchoredSearch(compiler, trace);
3243 3295
3244 EmitChoices(compiler, 3296 EmitChoices(compiler,
3245 &alt_gens, 3297 &alt_gens,
3246 0, 3298 0,
3247 trace, 3299 trace,
3248 &preload); 3300 &preload);
3249 } 3301 }
3250 3302
3251 // At this point we need to generate slow checks for the alternatives where 3303 // At this point we need to generate slow checks for the alternatives where
3252 // the quick check was inlined. We can recognize these because the associated 3304 // the quick check was inlined. We can recognize these because the associated
3253 // label was bound. 3305 // label was bound.
3254 int new_flush_budget = trace->flush_budget() / choice_count; 3306 intptr_t new_flush_budget = trace->flush_budget() / choice_count;
3255 for (int i = 0; i < choice_count; i++) { 3307 for (intptr_t i = 0; i < choice_count; i++) {
3256 AlternativeGeneration* alt_gen = alt_gens.at(i); 3308 AlternativeGeneration* alt_gen = alt_gens.at(i);
3257 Trace new_trace(*trace); 3309 Trace new_trace(*trace);
3258 // If there are actions to be flushed we have to limit how many times 3310 // If there are actions to be flushed we have to limit how many times
3259 // they are flushed. Take the budget of the parent trace and distribute 3311 // they are flushed. Take the budget of the parent trace and distribute
3260 // it fairly amongst the children. 3312 // it fairly amongst the children.
3261 if (new_trace.actions() != NULL) { 3313 if (new_trace.actions() != NULL) {
3262 new_trace.set_flush_budget(new_flush_budget); 3314 new_trace.set_flush_budget(new_flush_budget);
3263 } 3315 }
3264 bool next_expects_preload = 3316 bool next_expects_preload =
3265 i == choice_count - 1 ? false : alt_gens.at(i + 1)->expects_preload; 3317 i == choice_count - 1 ? false : alt_gens.at(i + 1)->expects_preload;
3266 EmitOutOfLineContinuation(compiler, 3318 EmitOutOfLineContinuation(compiler,
3267 &new_trace, 3319 &new_trace,
3268 alternatives_->at(i), 3320 alternatives_->At(i),
3269 alt_gen, 3321 alt_gen,
3270 preload.preload_characters_, 3322 preload.preload_characters_,
3271 next_expects_preload); 3323 next_expects_preload);
3272 } 3324 }
3273 } 3325 }
3274 3326
3275
3276 Trace* ChoiceNode::EmitGreedyLoop(RegExpCompiler* compiler, 3327 Trace* ChoiceNode::EmitGreedyLoop(RegExpCompiler* compiler,
3277 Trace* trace, 3328 Trace* trace,
3278 AlternativeGenerationList* alt_gens, 3329 AlternativeGenerationList* alt_gens,
3279 PreloadState* preload, 3330 PreloadState* preload,
3280 GreedyLoopState* greedy_loop_state, 3331 GreedyLoopState* greedy_loop_state,
3281 int text_length) { 3332 intptr_t text_length) {
3282 RegExpMacroAssembler* macro_assembler = compiler->macro_assembler(); 3333 RegExpMacroAssembler* macro_assembler = compiler->macro_assembler();
3283 // Here we have special handling for greedy loops containing only text nodes 3334 // Here we have special handling for greedy loops containing only text nodes
3284 // and other simple nodes. These are handled by pushing the current 3335 // and other simple nodes. These are handled by pushing the current
3285 // position on the stack and then incrementing the current position each 3336 // position on the stack and then incrementing the current position each
3286 // time around the switch. On backtrack we decrement the current position 3337 // time around the switch. On backtrack we decrement the current position
3287 // and check it against the pushed value. This avoids pushing backtrack 3338 // and check it against the pushed value. This avoids pushing backtrack
3288 // information for each iteration of the loop, which could take up a lot of 3339 // information for each iteration of the loop, which could take up a lot of
3289 // space. 3340 // space.
3290 DCHECK(trace->stop_node() == NULL); 3341 ASSERT(trace->stop_node() == NULL);
3291 macro_assembler->PushCurrentPosition(); 3342 macro_assembler->PushCurrentPosition();
3292 Label greedy_match_failed; 3343 BlockLabel greedy_match_failed;
3293 Trace greedy_match_trace; 3344 Trace greedy_match_trace;
3294 if (not_at_start()) greedy_match_trace.set_at_start(false); 3345 if (not_at_start()) greedy_match_trace.set_at_start(false);
3295 greedy_match_trace.set_backtrack(&greedy_match_failed); 3346 greedy_match_trace.set_backtrack(&greedy_match_failed);
3296 Label loop_label; 3347 BlockLabel loop_label;
3297 macro_assembler->Bind(&loop_label); 3348 macro_assembler->BindBlock(&loop_label);
3298 greedy_match_trace.set_stop_node(this); 3349 greedy_match_trace.set_stop_node(this);
3299 greedy_match_trace.set_loop_label(&loop_label); 3350 greedy_match_trace.set_loop_label(&loop_label);
3300 alternatives_->at(0).node()->Emit(compiler, &greedy_match_trace); 3351 (*alternatives_)[0].node()->Emit(compiler, &greedy_match_trace);
3301 macro_assembler->Bind(&greedy_match_failed); 3352 macro_assembler->BindBlock(&greedy_match_failed);
3302 3353
3303 Label second_choice; // For use in greedy matches. 3354 BlockLabel second_choice; // For use in greedy matches.
3304 macro_assembler->Bind(&second_choice); 3355 macro_assembler->BindBlock(&second_choice);
3305 3356
3306 Trace* new_trace = greedy_loop_state->counter_backtrack_trace(); 3357 Trace* new_trace = greedy_loop_state->counter_backtrack_trace();
3307 3358
3308 EmitChoices(compiler, 3359 EmitChoices(compiler,
3309 alt_gens, 3360 alt_gens,
3310 1, 3361 1,
3311 new_trace, 3362 new_trace,
3312 preload); 3363 preload);
3313 3364
3314 macro_assembler->Bind(greedy_loop_state->label()); 3365 macro_assembler->BindBlock(greedy_loop_state->label());
3315 // If we have unwound to the bottom then backtrack. 3366 // If we have unwound to the bottom then backtrack.
3316 macro_assembler->CheckGreedyLoop(trace->backtrack()); 3367 macro_assembler->CheckGreedyLoop(trace->backtrack());
3317 // Otherwise try the second priority at an earlier position. 3368 // Otherwise try the second priority at an earlier position.
3318 macro_assembler->AdvanceCurrentPosition(-text_length); 3369 macro_assembler->AdvanceCurrentPosition(-text_length);
3319 macro_assembler->GoTo(&second_choice); 3370 macro_assembler->GoTo(&second_choice);
3320 return new_trace; 3371 return new_trace;
3321 } 3372 }
3322 3373
3323 int ChoiceNode::EmitOptimizedUnanchoredSearch(RegExpCompiler* compiler, 3374
3324 Trace* trace) { 3375 intptr_t ChoiceNode::EmitOptimizedUnanchoredSearch(RegExpCompiler* compiler,
3325 int eats_at_least = PreloadState::kEatsAtLeastNotYetInitialized; 3376 Trace* trace) {
3377 intptr_t eats_at_least = PreloadState::kEatsAtLeastNotYetInitialized;
3326 if (alternatives_->length() != 2) return eats_at_least; 3378 if (alternatives_->length() != 2) return eats_at_least;
3327 3379
3328 GuardedAlternative alt1 = alternatives_->at(1); 3380 GuardedAlternative alt1 = alternatives_->At(1);
3329 if (alt1.guards() != NULL && alt1.guards()->length() != 0) { 3381 if (alt1.guards() != NULL && alt1.guards()->length() != 0) {
3330 return eats_at_least; 3382 return eats_at_least;
3331 } 3383 }
3332 RegExpNode* eats_anything_node = alt1.node(); 3384 RegExpNode* eats_anything_node = alt1.node();
3333 if (eats_anything_node->GetSuccessorOfOmnivorousTextNode(compiler) != this) { 3385 if (eats_anything_node->GetSuccessorOfOmnivorousTextNode(compiler) != this) {
3334 return eats_at_least; 3386 return eats_at_least;
3335 } 3387 }
3336 3388
3337 // Really we should be creating a new trace when we execute this function, 3389 // Really we should be creating a new trace when we execute this function,
3338 // but there is no need, because the code it generates cannot backtrack, and 3390 // but there is no need, because the code it generates cannot backtrack, and
3339 // we always arrive here with a trivial trace (since it's the entry to a 3391 // we always arrive here with a trivial trace (since it's the entry to a
3340 // loop. That also implies that there are no preloaded characters, which is 3392 // loop. That also implies that there are no preloaded characters, which is
3341 // good, because it means we won't be violating any assumptions by 3393 // good, because it means we won't be violating any assumptions by
3342 // overwriting those characters with new load instructions. 3394 // overwriting those characters with new load instructions.
3343 DCHECK(trace->is_trivial()); 3395 ASSERT(trace->is_trivial());
3344 3396
3345 RegExpMacroAssembler* macro_assembler = compiler->macro_assembler(); 3397 RegExpMacroAssembler* macro_assembler = compiler->macro_assembler();
3346 // At this point we know that we are at a non-greedy loop that will eat 3398 // At this point we know that we are at a non-greedy loop that will eat
3347 // any character one at a time. Any non-anchored regexp has such a 3399 // any character one at a time. Any non-anchored regexp has such a
3348 // loop prepended to it in order to find where it starts. We look for 3400 // loop prepended to it in order to find where it starts. We look for
3349 // a pattern of the form ...abc... where we can look 6 characters ahead 3401 // a pattern of the form ...abc... where we can look 6 characters ahead
3350 // and step forwards 3 if the character is not one of abc. Abc need 3402 // and step forwards 3 if the character is not one of abc. Abc need
3351 // not be atoms, they can be any reasonably limited character class or 3403 // not be atoms, they can be any reasonably limited character class or
3352 // small alternation. 3404 // small alternation.
3353 BoyerMooreLookahead* bm = bm_info(false); 3405 BoyerMooreLookahead* bm = bm_info(false);
3354 if (bm == NULL) { 3406 if (bm == NULL) {
3355 eats_at_least = Min(kMaxLookaheadForBoyerMoore, 3407 eats_at_least = Utils::Minimum(kMaxLookaheadForBoyerMoore,
3356 EatsAtLeast(kMaxLookaheadForBoyerMoore, 3408 EatsAtLeast(kMaxLookaheadForBoyerMoore,
3357 kRecursionBudget, 3409 kRecursionBudget,
3358 false)); 3410 false));
3359 if (eats_at_least >= 1) { 3411 if (eats_at_least >= 1) {
3360 bm = new(zone()) BoyerMooreLookahead(eats_at_least, 3412 bm = new(I) BoyerMooreLookahead(eats_at_least, compiler, I);
3361 compiler, 3413 GuardedAlternative alt0 = alternatives_->At(0);
3362 zone());
3363 GuardedAlternative alt0 = alternatives_->at(0);
3364 alt0.node()->FillInBMInfo(0, kRecursionBudget, bm, false); 3414 alt0.node()->FillInBMInfo(0, kRecursionBudget, bm, false);
3365 } 3415 }
3366 } 3416 }
3367 if (bm != NULL) { 3417 if (bm != NULL) {
3368 bm->EmitSkipInstructions(macro_assembler); 3418 bm->EmitSkipInstructions(macro_assembler);
3369 } 3419 }
3370 return eats_at_least; 3420 return eats_at_least;
3371 } 3421 }
3372 3422
3373 3423
3374 void ChoiceNode::EmitChoices(RegExpCompiler* compiler, 3424 void ChoiceNode::EmitChoices(RegExpCompiler* compiler,
3375 AlternativeGenerationList* alt_gens, 3425 AlternativeGenerationList* alt_gens,
3376 int first_choice, 3426 intptr_t first_choice,
3377 Trace* trace, 3427 Trace* trace,
3378 PreloadState* preload) { 3428 PreloadState* preload) {
3379 RegExpMacroAssembler* macro_assembler = compiler->macro_assembler(); 3429 RegExpMacroAssembler* macro_assembler = compiler->macro_assembler();
3380 SetUpPreLoad(compiler, trace, preload); 3430 SetUpPreLoad(compiler, trace, preload);
3381 3431
3382 // For now we just call all choices one after the other. The idea ultimately 3432 // For now we just call all choices one after the other. The idea ultimately
3383 // is to use the Dispatch table to try only the relevant ones. 3433 // is to use the Dispatch table to try only the relevant ones.
3384 int choice_count = alternatives_->length(); 3434 intptr_t choice_count = alternatives_->length();
3385 3435
3386 int new_flush_budget = trace->flush_budget() / choice_count; 3436 intptr_t new_flush_budget = trace->flush_budget() / choice_count;
3387 3437
3388 for (int i = first_choice; i < choice_count; i++) { 3438 for (intptr_t i = first_choice; i < choice_count; i++) {
3389 bool is_last = i == choice_count - 1; 3439 bool is_last = i == choice_count - 1;
3390 bool fall_through_on_failure = !is_last; 3440 bool fall_through_on_failure = !is_last;
3391 GuardedAlternative alternative = alternatives_->at(i); 3441 GuardedAlternative alternative = alternatives_->At(i);
3392 AlternativeGeneration* alt_gen = alt_gens->at(i); 3442 AlternativeGeneration* alt_gen = alt_gens->at(i);
3393 alt_gen->quick_check_details.set_characters(preload->preload_characters_); 3443 alt_gen->quick_check_details.set_characters(preload->preload_characters_);
3394 ZoneList<Guard*>* guards = alternative.guards(); 3444 ZoneGrowableArray<Guard*>* guards = alternative.guards();
3395 int guard_count = (guards == NULL) ? 0 : guards->length(); 3445 intptr_t guard_count = (guards == NULL) ? 0 : guards->length();
3396 Trace new_trace(*trace); 3446 Trace new_trace(*trace);
3397 new_trace.set_characters_preloaded(preload->preload_is_current_ ? 3447 new_trace.set_characters_preloaded(preload->preload_is_current_ ?
3398 preload->preload_characters_ : 3448 preload->preload_characters_ :
3399 0); 3449 0);
3400 if (preload->preload_has_checked_bounds_) { 3450 if (preload->preload_has_checked_bounds_) {
3401 new_trace.set_bound_checked_up_to(preload->preload_characters_); 3451 new_trace.set_bound_checked_up_to(preload->preload_characters_);
3402 } 3452 }
3403 new_trace.quick_check_performed()->Clear(); 3453 new_trace.quick_check_performed()->Clear();
3404 if (not_at_start_) new_trace.set_at_start(Trace::FALSE_VALUE); 3454 if (not_at_start_) new_trace.set_at_start(Trace::FALSE_VALUE);
3405 if (!is_last) { 3455 if (!is_last) {
3406 new_trace.set_backtrack(&alt_gen->after); 3456 new_trace.set_backtrack(&alt_gen->after);
3407 } 3457 }
3408 alt_gen->expects_preload = preload->preload_is_current_; 3458 alt_gen->expects_preload = preload->preload_is_current_;
3409 bool generate_full_check_inline = false; 3459 bool generate_full_check_inline = false;
3410 if (FLAG_regexp_optimization && 3460 if (kRegexpOptimization &&
3411 try_to_emit_quick_check_for_alternative(i == 0) && 3461 try_to_emit_quick_check_for_alternative(i == 0) &&
3412 alternative.node()->EmitQuickCheck(compiler, 3462 alternative.node()->EmitQuickCheck(compiler,
3413 trace, 3463 trace,
3414 &new_trace, 3464 &new_trace,
3415 preload->preload_has_checked_bounds_, 3465 preload->preload_has_checked_bounds_,
3416 &alt_gen->possible_success, 3466 &alt_gen->possible_success,
3417 &alt_gen->quick_check_details, 3467 &alt_gen->quick_check_details,
3418 fall_through_on_failure)) { 3468 fall_through_on_failure)) {
3419 // Quick check was generated for this choice. 3469 // Quick check was generated for this choice.
3420 preload->preload_is_current_ = true; 3470 preload->preload_is_current_ = true;
3421 preload->preload_has_checked_bounds_ = true; 3471 preload->preload_has_checked_bounds_ = true;
3422 // If we generated the quick check to fall through on possible success, 3472 // If we generated the quick check to fall through on possible success,
3423 // we now need to generate the full check inline. 3473 // we now need to generate the full check inline.
3424 if (!fall_through_on_failure) { 3474 if (!fall_through_on_failure) {
3425 macro_assembler->Bind(&alt_gen->possible_success); 3475 macro_assembler->BindBlock(&alt_gen->possible_success);
3426 new_trace.set_quick_check_performed(&alt_gen->quick_check_details); 3476 new_trace.set_quick_check_performed(&alt_gen->quick_check_details);
3427 new_trace.set_characters_preloaded(preload->preload_characters_); 3477 new_trace.set_characters_preloaded(preload->preload_characters_);
3428 new_trace.set_bound_checked_up_to(preload->preload_characters_); 3478 new_trace.set_bound_checked_up_to(preload->preload_characters_);
3429 generate_full_check_inline = true; 3479 generate_full_check_inline = true;
3430 } 3480 }
3431 } else if (alt_gen->quick_check_details.cannot_match()) { 3481 } else if (alt_gen->quick_check_details.cannot_match()) {
3432 if (!fall_through_on_failure) { 3482 if (!fall_through_on_failure) {
3433 macro_assembler->GoTo(trace->backtrack()); 3483 macro_assembler->GoTo(trace->backtrack());
3434 } 3484 }
3435 continue; 3485 continue;
3436 } else { 3486 } else {
3437 // No quick check was generated. Put the full code here. 3487 // No quick check was generated. Put the full code here.
3438 // If this is not the first choice then there could be slow checks from 3488 // If this is not the first choice then there could be slow checks from
3439 // previous cases that go here when they fail. There's no reason to 3489 // previous cases that go here when they fail. There's no reason to
3440 // insist that they preload characters since the slow check we are about 3490 // insist that they preload characters since the slow check we are about
3441 // to generate probably can't use it. 3491 // to generate probably can't use it.
3442 if (i != first_choice) { 3492 if (i != first_choice) {
3443 alt_gen->expects_preload = false; 3493 alt_gen->expects_preload = false;
3444 new_trace.InvalidateCurrentCharacter(); 3494 new_trace.InvalidateCurrentCharacter();
3445 } 3495 }
3446 generate_full_check_inline = true; 3496 generate_full_check_inline = true;
3447 } 3497 }
3448 if (generate_full_check_inline) { 3498 if (generate_full_check_inline) {
3449 if (new_trace.actions() != NULL) { 3499 if (new_trace.actions() != NULL) {
3450 new_trace.set_flush_budget(new_flush_budget); 3500 new_trace.set_flush_budget(new_flush_budget);
3451 } 3501 }
3452 for (int j = 0; j < guard_count; j++) { 3502 for (intptr_t j = 0; j < guard_count; j++) {
3453 GenerateGuard(macro_assembler, guards->at(j), &new_trace); 3503 GenerateGuard(macro_assembler, guards->At(j), &new_trace);
3454 } 3504 }
3455 alternative.node()->Emit(compiler, &new_trace); 3505 alternative.node()->Emit(compiler, &new_trace);
3456 preload->preload_is_current_ = false; 3506 preload->preload_is_current_ = false;
3457 } 3507 }
3458 macro_assembler->Bind(&alt_gen->after); 3508 macro_assembler->BindBlock(&alt_gen->after);
3459 } 3509 }
3460 } 3510 }
3461 3511
3462 3512
3463 void ChoiceNode::EmitOutOfLineContinuation(RegExpCompiler* compiler, 3513 void ChoiceNode::EmitOutOfLineContinuation(RegExpCompiler* compiler,
3464 Trace* trace, 3514 Trace* trace,
3465 GuardedAlternative alternative, 3515 GuardedAlternative alternative,
3466 AlternativeGeneration* alt_gen, 3516 AlternativeGeneration* alt_gen,
3467 int preload_characters, 3517 intptr_t preload_characters,
3468 bool next_expects_preload) { 3518 bool next_expects_preload) {
3469 if (!alt_gen->possible_success.is_linked()) return; 3519 if (!alt_gen->possible_success.IsLinked()) return;
3470 3520
3471 RegExpMacroAssembler* macro_assembler = compiler->macro_assembler(); 3521 RegExpMacroAssembler* macro_assembler = compiler->macro_assembler();
3472 macro_assembler->Bind(&alt_gen->possible_success); 3522 macro_assembler->BindBlock(&alt_gen->possible_success);
3473 Trace out_of_line_trace(*trace); 3523 Trace out_of_line_trace(*trace);
3474 out_of_line_trace.set_characters_preloaded(preload_characters); 3524 out_of_line_trace.set_characters_preloaded(preload_characters);
3475 out_of_line_trace.set_quick_check_performed(&alt_gen->quick_check_details); 3525 out_of_line_trace.set_quick_check_performed(&alt_gen->quick_check_details);
3476 if (not_at_start_) out_of_line_trace.set_at_start(Trace::FALSE_VALUE); 3526 if (not_at_start_) out_of_line_trace.set_at_start(Trace::FALSE_VALUE);
3477 ZoneList<Guard*>* guards = alternative.guards(); 3527 ZoneGrowableArray<Guard*>* guards = alternative.guards();
3478 int guard_count = (guards == NULL) ? 0 : guards->length(); 3528 intptr_t guard_count = (guards == NULL) ? 0 : guards->length();
3479 if (next_expects_preload) { 3529 if (next_expects_preload) {
3480 Label reload_current_char; 3530 BlockLabel reload_current_char;
3481 out_of_line_trace.set_backtrack(&reload_current_char); 3531 out_of_line_trace.set_backtrack(&reload_current_char);
3482 for (int j = 0; j < guard_count; j++) { 3532 for (intptr_t j = 0; j < guard_count; j++) {
3483 GenerateGuard(macro_assembler, guards->at(j), &out_of_line_trace); 3533 GenerateGuard(macro_assembler, guards->At(j), &out_of_line_trace);
3484 } 3534 }
3485 alternative.node()->Emit(compiler, &out_of_line_trace); 3535 alternative.node()->Emit(compiler, &out_of_line_trace);
3486 macro_assembler->Bind(&reload_current_char); 3536 macro_assembler->BindBlock(&reload_current_char);
3487 // Reload the current character, since the next quick check expects that. 3537 // Reload the current character, since the next quick check expects that.
3488 // We don't need to check bounds here because we only get into this 3538 // We don't need to check bounds here because we only get into this
3489 // code through a quick check which already did the checked load. 3539 // code through a quick check which already did the checked load.
3490 macro_assembler->LoadCurrentCharacter(trace->cp_offset(), 3540 macro_assembler->LoadCurrentCharacter(trace->cp_offset(),
3491 NULL, 3541 NULL,
3492 false, 3542 false,
3493 preload_characters); 3543 preload_characters);
3494 macro_assembler->GoTo(&(alt_gen->after)); 3544 macro_assembler->GoTo(&(alt_gen->after));
3495 } else { 3545 } else {
3496 out_of_line_trace.set_backtrack(&(alt_gen->after)); 3546 out_of_line_trace.set_backtrack(&(alt_gen->after));
3497 for (int j = 0; j < guard_count; j++) { 3547 for (intptr_t j = 0; j < guard_count; j++) {
3498 GenerateGuard(macro_assembler, guards->at(j), &out_of_line_trace); 3548 GenerateGuard(macro_assembler, guards->At(j), &out_of_line_trace);
3499 } 3549 }
3500 alternative.node()->Emit(compiler, &out_of_line_trace); 3550 alternative.node()->Emit(compiler, &out_of_line_trace);
3501 } 3551 }
3502 } 3552 }
3503 3553
3504 3554
3505 void ActionNode::Emit(RegExpCompiler* compiler, Trace* trace) { 3555 void ActionNode::Emit(RegExpCompiler* compiler, Trace* trace) {
3506 RegExpMacroAssembler* assembler = compiler->macro_assembler(); 3556 RegExpMacroAssembler* assembler = compiler->macro_assembler();
3507 LimitResult limit_result = LimitVersions(compiler, trace); 3557 LimitResult limit_result = LimitVersions(compiler, trace);
3508 if (limit_result == DONE) return; 3558 if (limit_result == DONE) return;
3509 DCHECK(limit_result == CONTINUE); 3559 ASSERT(limit_result == CONTINUE);
3510 3560
3511 RecursionCheck rc(compiler); 3561 RecursionCheck rc(compiler);
3512 3562
3513 switch (action_type_) { 3563 switch (action_type_) {
3514 case STORE_POSITION: { 3564 case STORE_POSITION: {
3515 Trace::DeferredCapture 3565 Trace::DeferredCapture
3516 new_capture(data_.u_position_register.reg, 3566 new_capture(data_.u_position_register.reg,
3517 data_.u_position_register.is_capture, 3567 data_.u_position_register.is_capture,
3518 trace); 3568 trace);
3519 Trace new_trace = *trace; 3569 Trace new_trace = *trace;
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
3551 trace->Flush(compiler, this); 3601 trace->Flush(compiler, this);
3552 } else { 3602 } else {
3553 assembler->WriteCurrentPositionToRegister( 3603 assembler->WriteCurrentPositionToRegister(
3554 data_.u_submatch.current_position_register, 0); 3604 data_.u_submatch.current_position_register, 0);
3555 assembler->WriteStackPointerToRegister( 3605 assembler->WriteStackPointerToRegister(
3556 data_.u_submatch.stack_pointer_register); 3606 data_.u_submatch.stack_pointer_register);
3557 on_success()->Emit(compiler, trace); 3607 on_success()->Emit(compiler, trace);
3558 } 3608 }
3559 break; 3609 break;
3560 case EMPTY_MATCH_CHECK: { 3610 case EMPTY_MATCH_CHECK: {
3561 int start_pos_reg = data_.u_empty_match_check.start_register; 3611 intptr_t start_pos_reg = data_.u_empty_match_check.start_register;
3562 int stored_pos = 0; 3612 intptr_t stored_pos = 0;
3563 int rep_reg = data_.u_empty_match_check.repetition_register; 3613 intptr_t rep_reg = data_.u_empty_match_check.repetition_register;
3564 bool has_minimum = (rep_reg != RegExpCompiler::kNoRegister); 3614 bool has_minimum = (rep_reg != RegExpCompiler::kNoRegister);
3565 bool know_dist = trace->GetStoredPosition(start_pos_reg, &stored_pos); 3615 bool know_dist = trace->GetStoredPosition(start_pos_reg, &stored_pos);
3566 if (know_dist && !has_minimum && stored_pos == trace->cp_offset()) { 3616 if (know_dist && !has_minimum && stored_pos == trace->cp_offset()) {
3567 // If we know we haven't advanced and there is no minimum we 3617 // If we know we haven't advanced and there is no minimum we
3568 // can just backtrack immediately. 3618 // can just backtrack immediately.
3569 assembler->GoTo(trace->backtrack()); 3619 assembler->GoTo(trace->backtrack());
3570 } else if (know_dist && stored_pos < trace->cp_offset()) { 3620 } else if (know_dist && stored_pos < trace->cp_offset()) {
3571 // If we know we've advanced we can generate the continuation 3621 // If we know we've advanced we can generate the continuation
3572 // immediately. 3622 // immediately.
3573 on_success()->Emit(compiler, trace); 3623 on_success()->Emit(compiler, trace);
3574 } else if (!trace->is_trivial()) { 3624 } else if (!trace->is_trivial()) {
3575 trace->Flush(compiler, this); 3625 trace->Flush(compiler, this);
3576 } else { 3626 } else {
3577 Label skip_empty_check; 3627 BlockLabel skip_empty_check;
3578 // If we have a minimum number of repetitions we check the current 3628 // If we have a minimum number of repetitions we check the current
3579 // number first and skip the empty check if it's not enough. 3629 // number first and skip the empty check if it's not enough.
3580 if (has_minimum) { 3630 if (has_minimum) {
3581 int limit = data_.u_empty_match_check.repetition_limit; 3631 intptr_t limit = data_.u_empty_match_check.repetition_limit;
3582 assembler->IfRegisterLT(rep_reg, limit, &skip_empty_check); 3632 assembler->IfRegisterLT(rep_reg, limit, &skip_empty_check);
3583 } 3633 }
3584 // If the match is empty we bail out, otherwise we fall through 3634 // If the match is empty we bail out, otherwise we fall through
3585 // to the on-success continuation. 3635 // to the on-success continuation.
3586 assembler->IfRegisterEqPos(data_.u_empty_match_check.start_register, 3636 assembler->IfRegisterEqPos(data_.u_empty_match_check.start_register,
3587 trace->backtrack()); 3637 trace->backtrack());
3588 assembler->Bind(&skip_empty_check); 3638 assembler->BindBlock(&skip_empty_check);
3589 on_success()->Emit(compiler, trace); 3639 on_success()->Emit(compiler, trace);
3590 } 3640 }
3591 break; 3641 break;
3592 } 3642 }
3593 case POSITIVE_SUBMATCH_SUCCESS: { 3643 case POSITIVE_SUBMATCH_SUCCESS: {
3594 if (!trace->is_trivial()) { 3644 if (!trace->is_trivial()) {
3595 trace->Flush(compiler, this); 3645 trace->Flush(compiler, this);
3596 return; 3646 return;
3597 } 3647 }
3598 assembler->ReadCurrentPositionFromRegister( 3648 assembler->ReadCurrentPositionFromRegister(
3599 data_.u_submatch.current_position_register); 3649 data_.u_submatch.current_position_register);
3600 assembler->ReadStackPointerFromRegister( 3650 assembler->ReadStackPointerFromRegister(
3601 data_.u_submatch.stack_pointer_register); 3651 data_.u_submatch.stack_pointer_register);
3602 int clear_register_count = data_.u_submatch.clear_register_count; 3652 intptr_t clear_register_count = data_.u_submatch.clear_register_count;
3603 if (clear_register_count == 0) { 3653 if (clear_register_count == 0) {
3604 on_success()->Emit(compiler, trace); 3654 on_success()->Emit(compiler, trace);
3605 return; 3655 return;
3606 } 3656 }
3607 int clear_registers_from = data_.u_submatch.clear_register_from; 3657 intptr_t clear_registers_from = data_.u_submatch.clear_register_from;
3608 Label clear_registers_backtrack; 3658 BlockLabel clear_registers_backtrack;
3609 Trace new_trace = *trace; 3659 Trace new_trace = *trace;
3610 new_trace.set_backtrack(&clear_registers_backtrack); 3660 new_trace.set_backtrack(&clear_registers_backtrack);
3611 on_success()->Emit(compiler, &new_trace); 3661 on_success()->Emit(compiler, &new_trace);
3612 3662
3613 assembler->Bind(&clear_registers_backtrack); 3663 assembler->BindBlock(&clear_registers_backtrack);
3614 int clear_registers_to = clear_registers_from + clear_register_count - 1; 3664 intptr_t clear_registers_to =
3665 clear_registers_from + clear_register_count - 1;
3615 assembler->ClearRegisters(clear_registers_from, clear_registers_to); 3666 assembler->ClearRegisters(clear_registers_from, clear_registers_to);
3616 3667
3617 DCHECK(trace->backtrack() == NULL); 3668 ASSERT(trace->backtrack() == NULL);
3618 assembler->Backtrack(); 3669 assembler->Backtrack();
3619 return; 3670 return;
3620 } 3671 }
3621 default: 3672 default:
3622 UNREACHABLE(); 3673 UNREACHABLE();
3623 } 3674 }
3624 } 3675 }
3625 3676
3626 3677
3627 void BackReferenceNode::Emit(RegExpCompiler* compiler, Trace* trace) { 3678 void BackReferenceNode::Emit(RegExpCompiler* compiler, Trace* trace) {
3628 RegExpMacroAssembler* assembler = compiler->macro_assembler(); 3679 RegExpMacroAssembler* assembler = compiler->macro_assembler();
3629 if (!trace->is_trivial()) { 3680 if (!trace->is_trivial()) {
3630 trace->Flush(compiler, this); 3681 trace->Flush(compiler, this);
3631 return; 3682 return;
3632 } 3683 }
3633 3684
3634 LimitResult limit_result = LimitVersions(compiler, trace); 3685 LimitResult limit_result = LimitVersions(compiler, trace);
3635 if (limit_result == DONE) return; 3686 if (limit_result == DONE) return;
3636 DCHECK(limit_result == CONTINUE); 3687 ASSERT(limit_result == CONTINUE);
3637 3688
3638 RecursionCheck rc(compiler); 3689 RecursionCheck rc(compiler);
3639 3690
3640 DCHECK_EQ(start_reg_ + 1, end_reg_); 3691 ASSERT(start_reg_ + 1 == end_reg_);
3641 if (compiler->ignore_case()) { 3692 if (compiler->ignore_case()) {
3642 assembler->CheckNotBackReferenceIgnoreCase(start_reg_, 3693 assembler->CheckNotBackReferenceIgnoreCase(start_reg_,
3643 trace->backtrack()); 3694 trace->backtrack());
3644 } else { 3695 } else {
3645 assembler->CheckNotBackReference(start_reg_, trace->backtrack()); 3696 assembler->CheckNotBackReference(start_reg_, trace->backtrack());
3646 } 3697 }
3647 on_success()->Emit(compiler, trace); 3698 on_success()->Emit(compiler, trace);
3648 } 3699 }
3649 3700
3650 3701
3651 // ------------------------------------------------------------------- 3702 // -------------------------------------------------------------------
3652 // Dot/dotty output 3703 // Dot/dotty output
3653 3704
3654 3705
3655 #ifdef DEBUG 3706 #ifdef DEBUG
3656 3707
3657 3708
3658 class DotPrinter: public NodeVisitor { 3709 class DotPrinter: public NodeVisitor {
3659 public: 3710 public:
3660 DotPrinter(OStream& os, bool ignore_case) // NOLINT 3711 explicit DotPrinter(bool ignore_case)
3661 : os_(os), 3712 : ignore_case_(ignore_case) {}
3662 ignore_case_(ignore_case) {}
3663 void PrintNode(const char* label, RegExpNode* node); 3713 void PrintNode(const char* label, RegExpNode* node);
3664 void Visit(RegExpNode* node); 3714 void Visit(RegExpNode* node);
3665 void PrintAttributes(RegExpNode* from); 3715 void PrintAttributes(RegExpNode* from);
3666 void PrintOnFailure(RegExpNode* from, RegExpNode* to); 3716 void PrintOnFailure(RegExpNode* from, RegExpNode* to);
3667 #define DECLARE_VISIT(Type) \ 3717 #define DECLARE_VISIT(Type) \
3668 virtual void Visit##Type(Type##Node* that); 3718 virtual void Visit##Type(Type##Node* that);
3669 FOR_EACH_NODE_TYPE(DECLARE_VISIT) 3719 FOR_EACH_NODE_TYPE(DECLARE_VISIT)
3670 #undef DECLARE_VISIT 3720 #undef DECLARE_VISIT
3671 private: 3721 private:
3672 OStream& os_;
3673 bool ignore_case_; 3722 bool ignore_case_;
3674 }; 3723 };
3675 3724
3676 3725
3677 void DotPrinter::PrintNode(const char* label, RegExpNode* node) { 3726 void DotPrinter::PrintNode(const char* label, RegExpNode* node) {
3678 os_ << "digraph G {\n graph [label=\""; 3727 OS::Print("digraph G {\n graph [label=\"");
3679 for (int i = 0; label[i]; i++) { 3728 for (intptr_t i = 0; label[i]; i++) {
3680 switch (label[i]) { 3729 switch (label[i]) {
3681 case '\\': 3730 case '\\':
3682 os_ << "\\\\"; 3731 OS::Print("\\\\");
3683 break; 3732 break;
3684 case '"': 3733 case '"':
3685 os_ << "\""; 3734 OS::Print("\"");
3686 break; 3735 break;
3687 default: 3736 default:
3688 os_ << label[i]; 3737 OS::Print("%c", label[i]);
3689 break; 3738 break;
3690 } 3739 }
3691 } 3740 }
3692 os_ << "\"];\n"; 3741 OS::Print("\"];\n");
3693 Visit(node); 3742 Visit(node);
3694 os_ << "}" << endl; 3743 OS::Print("}\n");
3695 } 3744 }
3696 3745
3697 3746
3698 void DotPrinter::Visit(RegExpNode* node) { 3747 void DotPrinter::Visit(RegExpNode* node) {
3699 if (node->info()->visited) return; 3748 if (node->info()->visited) return;
3700 node->info()->visited = true; 3749 node->info()->visited = true;
3701 node->Accept(this); 3750 node->Accept(this);
3702 } 3751 }
3703 3752
3704 3753
3705 void DotPrinter::PrintOnFailure(RegExpNode* from, RegExpNode* on_failure) { 3754 void DotPrinter::PrintOnFailure(RegExpNode* from, RegExpNode* on_failure) {
3706 os_ << " n" << from << " -> n" << on_failure << " [style=dotted];\n"; 3755 OS::Print(" n%p -> n%p [style=dotted];\n", from, on_failure);
3707 Visit(on_failure); 3756 Visit(on_failure);
3708 } 3757 }
3709 3758
3710 3759
3711 class TableEntryBodyPrinter { 3760 class AttributePrinter : public ValueObject {
3712 public: 3761 public:
3713 TableEntryBodyPrinter(OStream& os, ChoiceNode* choice) // NOLINT 3762 AttributePrinter() : first_(true) {}
3714 : os_(os),
3715 choice_(choice) {}
3716 void Call(uc16 from, DispatchTable::Entry entry) {
3717 OutSet* out_set = entry.out_set();
3718 for (unsigned i = 0; i < OutSet::kFirstLimit; i++) {
3719 if (out_set->Get(i)) {
3720 os_ << " n" << choice() << ":s" << from << "o" << i << " -> n"
3721 << choice()->alternatives()->at(i).node() << ";\n";
3722 }
3723 }
3724 }
3725 private:
3726 ChoiceNode* choice() { return choice_; }
3727 OStream& os_;
3728 ChoiceNode* choice_;
3729 };
3730
3731
3732 class TableEntryHeaderPrinter {
3733 public:
3734 explicit TableEntryHeaderPrinter(OStream& os) // NOLINT
3735 : first_(true),
3736 os_(os) {}
3737 void Call(uc16 from, DispatchTable::Entry entry) {
3738 if (first_) {
3739 first_ = false;
3740 } else {
3741 os_ << "|";
3742 }
3743 os_ << "{\\" << AsUC16(from) << "-\\" << AsUC16(entry.to()) << "|{";
3744 OutSet* out_set = entry.out_set();
3745 int priority = 0;
3746 for (unsigned i = 0; i < OutSet::kFirstLimit; i++) {
3747 if (out_set->Get(i)) {
3748 if (priority > 0) os_ << "|";
3749 os_ << "<s" << from << "o" << i << "> " << priority;
3750 priority++;
3751 }
3752 }
3753 os_ << "}}";
3754 }
3755
3756 private:
3757 bool first_;
3758 OStream& os_;
3759 };
3760
3761
3762 class AttributePrinter {
3763 public:
3764 explicit AttributePrinter(OStream& os) // NOLINT
3765 : os_(os),
3766 first_(true) {}
3767 void PrintSeparator() { 3763 void PrintSeparator() {
3768 if (first_) { 3764 if (first_) {
3769 first_ = false; 3765 first_ = false;
3770 } else { 3766 } else {
3771 os_ << "|"; 3767 OS::Print("|");
3772 } 3768 }
3773 } 3769 }
3774 void PrintBit(const char* name, bool value) { 3770 void PrintBit(const char* name, bool value) {
3775 if (!value) return; 3771 if (!value) return;
3776 PrintSeparator(); 3772 PrintSeparator();
3777 os_ << "{" << name << "}"; 3773 OS::Print("{%s}", name);
3778 } 3774 }
3779 void PrintPositive(const char* name, int value) { 3775 void PrintPositive(const char* name, intptr_t value) {
3780 if (value < 0) return; 3776 if (value < 0) return;
3781 PrintSeparator(); 3777 PrintSeparator();
3782 os_ << "{" << name << "|" << value << "}"; 3778 OS::Print("{%s|%" Pd "}", name, value);
3783 } 3779 }
3784 3780
3785 private: 3781 private:
3786 OStream& os_;
3787 bool first_; 3782 bool first_;
3788 }; 3783 };
3789 3784
3790 3785
3791 void DotPrinter::PrintAttributes(RegExpNode* that) { 3786 void DotPrinter::PrintAttributes(RegExpNode* that) {
3792 os_ << " a" << that << " [shape=Mrecord, color=grey, fontcolor=grey, " 3787 OS::Print(" a%p [shape=Mrecord, color=grey, fontcolor=grey, "
3793 << "margin=0.1, fontsize=10, label=\"{"; 3788 "margin=0.1, fontsize=10, label=\"{", that);
3794 AttributePrinter printer(os_); 3789 AttributePrinter printer;
3795 NodeInfo* info = that->info(); 3790 NodeInfo* info = that->info();
3796 printer.PrintBit("NI", info->follows_newline_interest); 3791 printer.PrintBit("NI", info->follows_newline_interest);
3797 printer.PrintBit("WI", info->follows_word_interest); 3792 printer.PrintBit("WI", info->follows_word_interest);
3798 printer.PrintBit("SI", info->follows_start_interest); 3793 printer.PrintBit("SI", info->follows_start_interest);
3799 Label* label = that->label(); 3794 BlockLabel* label = that->label();
3800 if (label->is_bound()) 3795 if (label->IsBound())
3801 printer.PrintPositive("@", label->pos()); 3796 printer.PrintPositive("@", label->Position());
3802 os_ << "}\"];\n" 3797 OS::Print("}\"];\n"
3803 << " a" << that << " -> n" << that 3798 " a%p -> n%p [style=dashed, color=grey, arrowhead=none];\n",
3804 << " [style=dashed, color=grey, arrowhead=none];\n"; 3799 that, that);
3805 } 3800 }
3806 3801
3807 3802
3808 static const bool kPrintDispatchTable = false;
3809 void DotPrinter::VisitChoice(ChoiceNode* that) { 3803 void DotPrinter::VisitChoice(ChoiceNode* that) {
3810 if (kPrintDispatchTable) { 3804 OS::Print(" n%p [shape=Mrecord, label=\"?\"];\n", that);
3811 os_ << " n" << that << " [shape=Mrecord, label=\""; 3805 for (intptr_t i = 0; i < that->alternatives()->length(); i++) {
3812 TableEntryHeaderPrinter header_printer(os_); 3806 GuardedAlternative alt = that->alternatives()->At(i);
3813 that->GetTable(ignore_case_)->ForEach(&header_printer); 3807 OS::Print(" n%p -> n%p", that, alt.node());
3814 os_ << "\"]\n";
3815 PrintAttributes(that);
3816 TableEntryBodyPrinter body_printer(os_, that);
3817 that->GetTable(ignore_case_)->ForEach(&body_printer);
3818 } else {
3819 os_ << " n" << that << " [shape=Mrecord, label=\"?\"];\n";
3820 for (int i = 0; i < that->alternatives()->length(); i++) {
3821 GuardedAlternative alt = that->alternatives()->at(i);
3822 os_ << " n" << that << " -> n" << alt.node();
3823 }
3824 } 3808 }
3825 for (int i = 0; i < that->alternatives()->length(); i++) { 3809 for (intptr_t i = 0; i < that->alternatives()->length(); i++) {
3826 GuardedAlternative alt = that->alternatives()->at(i); 3810 GuardedAlternative alt = that->alternatives()->At(i);
3827 alt.node()->Accept(this); 3811 alt.node()->Accept(this);
3828 } 3812 }
3829 } 3813 }
3830 3814
3831 3815
3832 void DotPrinter::VisitText(TextNode* that) { 3816 void DotPrinter::VisitText(TextNode* that) {
3833 Zone* zone = that->zone(); 3817 OS::Print(" n%p [label=\"", that);
3834 os_ << " n" << that << " [label=\""; 3818 for (intptr_t i = 0; i < that->elements()->length(); i++) {
3835 for (int i = 0; i < that->elements()->length(); i++) { 3819 if (i > 0) OS::Print(" ");
3836 if (i > 0) os_ << " "; 3820 TextElement elm = that->elements()->At(i);
3837 TextElement elm = that->elements()->at(i);
3838 switch (elm.text_type()) { 3821 switch (elm.text_type()) {
3839 case TextElement::ATOM: { 3822 case TextElement::ATOM: {
3840 Vector<const uc16> data = elm.atom()->data(); 3823 ZoneGrowableArray<uint16_t>* data = elm.atom()->data();
3841 for (int i = 0; i < data.length(); i++) { 3824 for (intptr_t i = 0; i < data->length(); i++) {
3842 os_ << static_cast<char>(data[i]); 3825 OS::Print("%c", static_cast<char>(data->At(i)));
3843 } 3826 }
3844 break; 3827 break;
3845 } 3828 }
3846 case TextElement::CHAR_CLASS: { 3829 case TextElement::CHAR_CLASS: {
3847 RegExpCharacterClass* node = elm.char_class(); 3830 RegExpCharacterClass* node = elm.char_class();
3848 os_ << "["; 3831 OS::Print("[");
3849 if (node->is_negated()) os_ << "^"; 3832 if (node->is_negated()) OS::Print("^");
3850 for (int j = 0; j < node->ranges(zone)->length(); j++) { 3833 for (intptr_t j = 0; j < node->ranges()->length(); j++) {
3851 CharacterRange range = node->ranges(zone)->at(j); 3834 CharacterRange range = node->ranges()->At(j);
3852 os_ << AsUC16(range.from()) << "-" << AsUC16(range.to()); 3835 PrintUtf16(range.from());
3836 OS::Print("-");
3837 PrintUtf16(range.to());
3853 } 3838 }
3854 os_ << "]"; 3839 OS::Print("]");
3855 break; 3840 break;
3856 } 3841 }
3857 default: 3842 default:
3858 UNREACHABLE(); 3843 UNREACHABLE();
3859 } 3844 }
3860 } 3845 }
3861 os_ << "\", shape=box, peripheries=2];\n"; 3846 OS::Print("\", shape=box, peripheries=2];\n");
3862 PrintAttributes(that); 3847 PrintAttributes(that);
3863 os_ << " n" << that << " -> n" << that->on_success() << ";\n"; 3848 OS::Print(" n%p -> n%p;\n", that, that->on_success());
3864 Visit(that->on_success()); 3849 Visit(that->on_success());
3865 } 3850 }
3866 3851
3867 3852
3868 void DotPrinter::VisitBackReference(BackReferenceNode* that) { 3853 void DotPrinter::VisitBackReference(BackReferenceNode* that) {
3869 os_ << " n" << that << " [label=\"$" << that->start_register() << "..$" 3854 OS::Print(" n%p [label=\"$%" Pd "..$%" Pd "\", shape=doubleoctagon];\n",
3870 << that->end_register() << "\", shape=doubleoctagon];\n"; 3855 that, that->start_register(), that->end_register());
3871 PrintAttributes(that); 3856 PrintAttributes(that);
3872 os_ << " n" << that << " -> n" << that->on_success() << ";\n"; 3857 OS::Print(" n%p -> n%p;\n", that, that->on_success());
3873 Visit(that->on_success()); 3858 Visit(that->on_success());
3874 } 3859 }
3875 3860
3876 3861
3877 void DotPrinter::VisitEnd(EndNode* that) { 3862 void DotPrinter::VisitEnd(EndNode* that) {
3878 os_ << " n" << that << " [style=bold, shape=point];\n"; 3863 OS::Print(" n%p [style=bold, shape=point];\n", that);
3879 PrintAttributes(that); 3864 PrintAttributes(that);
3880 } 3865 }
3881 3866
3882 3867
3883 void DotPrinter::VisitAssertion(AssertionNode* that) { 3868 void DotPrinter::VisitAssertion(AssertionNode* that) {
3884 os_ << " n" << that << " ["; 3869 OS::Print(" n%p [", that);
3885 switch (that->assertion_type()) { 3870 switch (that->assertion_type()) {
3886 case AssertionNode::AT_END: 3871 case AssertionNode::AT_END:
3887 os_ << "label=\"$\", shape=septagon"; 3872 OS::Print("label=\"$\", shape=septagon");
3888 break; 3873 break;
3889 case AssertionNode::AT_START: 3874 case AssertionNode::AT_START:
3890 os_ << "label=\"^\", shape=septagon"; 3875 OS::Print("label=\"^\", shape=septagon");
3891 break; 3876 break;
3892 case AssertionNode::AT_BOUNDARY: 3877 case AssertionNode::AT_BOUNDARY:
3893 os_ << "label=\"\\b\", shape=septagon"; 3878 OS::Print("label=\"\\b\", shape=septagon");
3894 break; 3879 break;
3895 case AssertionNode::AT_NON_BOUNDARY: 3880 case AssertionNode::AT_NON_BOUNDARY:
3896 os_ << "label=\"\\B\", shape=septagon"; 3881 OS::Print("label=\"\\B\", shape=septagon");
3897 break; 3882 break;
3898 case AssertionNode::AFTER_NEWLINE: 3883 case AssertionNode::AFTER_NEWLINE:
3899 os_ << "label=\"(?<=\\n)\", shape=septagon"; 3884 OS::Print("label=\"(?<=\\n)\", shape=septagon");
3900 break; 3885 break;
3901 } 3886 }
3902 os_ << "];\n"; 3887 OS::Print("];\n");
3903 PrintAttributes(that); 3888 PrintAttributes(that);
3904 RegExpNode* successor = that->on_success(); 3889 RegExpNode* successor = that->on_success();
3905 os_ << " n" << that << " -> n" << successor << ";\n"; 3890 OS::Print(" n%p -> n%p;\n", that, successor);
3906 Visit(successor); 3891 Visit(successor);
3907 } 3892 }
3908 3893
3909 3894
3910 void DotPrinter::VisitAction(ActionNode* that) { 3895 void DotPrinter::VisitAction(ActionNode* that) {
3911 os_ << " n" << that << " ["; 3896 OS::Print(" n%p [", that);
3912 switch (that->action_type_) { 3897 switch (that->action_type_) {
3913 case ActionNode::SET_REGISTER: 3898 case ActionNode::SET_REGISTER:
3914 os_ << "label=\"$" << that->data_.u_store_register.reg 3899 OS::Print("label=\"$%" Pd ":=%" Pd "\", shape=octagon",
3915 << ":=" << that->data_.u_store_register.value << "\", shape=octagon"; 3900 that->data_.u_store_register.reg,
3901 that->data_.u_store_register.value);
3916 break; 3902 break;
3917 case ActionNode::INCREMENT_REGISTER: 3903 case ActionNode::INCREMENT_REGISTER:
3918 os_ << "label=\"$" << that->data_.u_increment_register.reg 3904 OS::Print("label=\"$%" Pd "++\", shape=octagon",
3919 << "++\", shape=octagon"; 3905 that->data_.u_increment_register.reg);
3920 break; 3906 break;
3921 case ActionNode::STORE_POSITION: 3907 case ActionNode::STORE_POSITION:
3922 os_ << "label=\"$" << that->data_.u_position_register.reg 3908 OS::Print("label=\"$%" Pd ":=$pos\", shape=octagon",
3923 << ":=$pos\", shape=octagon"; 3909 that->data_.u_position_register.reg);
3924 break; 3910 break;
3925 case ActionNode::BEGIN_SUBMATCH: 3911 case ActionNode::BEGIN_SUBMATCH:
3926 os_ << "label=\"$" << that->data_.u_submatch.current_position_register 3912 OS::Print("label=\"$%" Pd ":=$pos,begin\", shape=septagon",
3927 << ":=$pos,begin\", shape=septagon"; 3913 that->data_.u_submatch.current_position_register);
3928 break; 3914 break;
3929 case ActionNode::POSITIVE_SUBMATCH_SUCCESS: 3915 case ActionNode::POSITIVE_SUBMATCH_SUCCESS:
3930 os_ << "label=\"escape\", shape=septagon"; 3916 OS::Print("label=\"escape\", shape=septagon");
3931 break; 3917 break;
3932 case ActionNode::EMPTY_MATCH_CHECK: 3918 case ActionNode::EMPTY_MATCH_CHECK:
3933 os_ << "label=\"$" << that->data_.u_empty_match_check.start_register 3919 OS::Print("label=\"$%" Pd "=$pos?,$%" Pd "<%" Pd "?\", shape=septagon",
3934 << "=$pos?,$" << that->data_.u_empty_match_check.repetition_register 3920 that->data_.u_empty_match_check.start_register,
3935 << "<" << that->data_.u_empty_match_check.repetition_limit 3921 that->data_.u_empty_match_check.repetition_register,
3936 << "?\", shape=septagon"; 3922 that->data_.u_empty_match_check.repetition_limit);
3937 break; 3923 break;
3938 case ActionNode::CLEAR_CAPTURES: { 3924 case ActionNode::CLEAR_CAPTURES: {
3939 os_ << "label=\"clear $" << that->data_.u_clear_captures.range_from 3925 OS::Print("label=\"clear $%" Pd " to $%" Pd "\", shape=septagon",
3940 << " to $" << that->data_.u_clear_captures.range_to 3926 that->data_.u_clear_captures.range_from,
3941 << "\", shape=septagon"; 3927 that->data_.u_clear_captures.range_to);
3942 break; 3928 break;
3943 } 3929 }
3944 } 3930 }
3945 os_ << "];\n"; 3931 OS::Print("];\n");
3946 PrintAttributes(that); 3932 PrintAttributes(that);
3947 RegExpNode* successor = that->on_success(); 3933 RegExpNode* successor = that->on_success();
3948 os_ << " n" << that << " -> n" << successor << ";\n"; 3934 OS::Print(" n%p -> n%p;\n", that, successor);
3949 Visit(successor); 3935 Visit(successor);
3950 } 3936 }
3951 3937
3952 3938
3953 class DispatchTableDumper {
3954 public:
3955 explicit DispatchTableDumper(OStream& os) : os_(os) {}
3956 void Call(uc16 key, DispatchTable::Entry entry);
3957 private:
3958 OStream& os_;
3959 };
3960
3961
3962 void DispatchTableDumper::Call(uc16 key, DispatchTable::Entry entry) {
3963 os_ << "[" << AsUC16(key) << "-" << AsUC16(entry.to()) << "]: {";
3964 OutSet* set = entry.out_set();
3965 bool first = true;
3966 for (unsigned i = 0; i < OutSet::kFirstLimit; i++) {
3967 if (set->Get(i)) {
3968 if (first) {
3969 first = false;
3970 } else {
3971 os_ << ", ";
3972 }
3973 os_ << i;
3974 }
3975 }
3976 os_ << "}\n";
3977 }
3978
3979
3980 void DispatchTable::Dump() {
3981 OFStream os(stderr);
3982 DispatchTableDumper dumper(os);
3983 tree()->ForEach(&dumper);
3984 }
3985
3986
3987 void RegExpEngine::DotPrint(const char* label, 3939 void RegExpEngine::DotPrint(const char* label,
3988 RegExpNode* node, 3940 RegExpNode* node,
3989 bool ignore_case) { 3941 bool ignore_case) {
3990 OFStream os(stdout); 3942 DotPrinter printer(ignore_case);
3991 DotPrinter printer(os, ignore_case);
3992 printer.PrintNode(label, node); 3943 printer.PrintNode(label, node);
3993 } 3944 }
3994 3945
3995 3946
3996 #endif // DEBUG 3947 #endif // DEBUG
3997 3948
3998 3949
3999 // ------------------------------------------------------------------- 3950 // -------------------------------------------------------------------
4000 // Tree to graph conversion 3951 // Tree to graph conversion
4001 3952
4002 RegExpNode* RegExpAtom::ToNode(RegExpCompiler* compiler, 3953 RegExpNode* RegExpAtom::ToNode(RegExpCompiler* compiler,
4003 RegExpNode* on_success) { 3954 RegExpNode* on_success) {
4004 ZoneList<TextElement>* elms = 3955 ZoneGrowableArray<TextElement>* elms =
4005 new(compiler->zone()) ZoneList<TextElement>(1, compiler->zone()); 3956 new(CI) ZoneGrowableArray<TextElement>(1);
4006 elms->Add(TextElement::Atom(this), compiler->zone()); 3957 elms->Add(TextElement::Atom(this));
4007 return new(compiler->zone()) TextNode(elms, on_success); 3958 return new(CI) TextNode(elms, on_success);
4008 } 3959 }
4009 3960
4010 3961
4011 RegExpNode* RegExpText::ToNode(RegExpCompiler* compiler, 3962 RegExpNode* RegExpText::ToNode(RegExpCompiler* compiler,
4012 RegExpNode* on_success) { 3963 RegExpNode* on_success) {
4013 return new(compiler->zone()) TextNode(elements(), on_success); 3964 ZoneGrowableArray<TextElement>* elms =
3965 new(CI) ZoneGrowableArray<TextElement>(1);
3966 for (intptr_t i = 0; i < elements()->length(); i++) {
3967 elms->Add(elements()->At(i));
3968 }
3969 return new(CI) TextNode(elms, on_success);
4014 } 3970 }
4015 3971
4016 3972
4017 static bool CompareInverseRanges(ZoneList<CharacterRange>* ranges, 3973 static bool CompareInverseRanges(ZoneGrowableArray<CharacterRange>* ranges,
4018 const int* special_class, 3974 const intptr_t* special_class,
4019 int length) { 3975 intptr_t length) {
4020 length--; // Remove final 0x10000. 3976 length--; // Remove final 0x10000.
4021 DCHECK(special_class[length] == 0x10000); 3977 ASSERT(special_class[length] == 0x10000);
4022 DCHECK(ranges->length() != 0); 3978 ASSERT(ranges->length() != 0);
4023 DCHECK(length != 0); 3979 ASSERT(length != 0);
4024 DCHECK(special_class[0] != 0); 3980 ASSERT(special_class[0] != 0);
4025 if (ranges->length() != (length >> 1) + 1) { 3981 if (ranges->length() != (length >> 1) + 1) {
4026 return false; 3982 return false;
4027 } 3983 }
4028 CharacterRange range = ranges->at(0); 3984 CharacterRange range = ranges->At(0);
4029 if (range.from() != 0) { 3985 if (range.from() != 0) {
4030 return false; 3986 return false;
4031 } 3987 }
4032 for (int i = 0; i < length; i += 2) { 3988 for (intptr_t i = 0; i < length; i += 2) {
4033 if (special_class[i] != (range.to() + 1)) { 3989 if (special_class[i] != (range.to() + 1)) {
4034 return false; 3990 return false;
4035 } 3991 }
4036 range = ranges->at((i >> 1) + 1); 3992 range = ranges->At((i >> 1) + 1);
4037 if (special_class[i+1] != range.from()) { 3993 if (special_class[i+1] != range.from()) {
4038 return false; 3994 return false;
4039 } 3995 }
4040 } 3996 }
4041 if (range.to() != 0xffff) { 3997 if (range.to() != 0xffff) {
4042 return false; 3998 return false;
4043 } 3999 }
4044 return true; 4000 return true;
4045 } 4001 }
4046 4002
4047 4003
4048 static bool CompareRanges(ZoneList<CharacterRange>* ranges, 4004 static bool CompareRanges(ZoneGrowableArray<CharacterRange>* ranges,
4049 const int* special_class, 4005 const intptr_t* special_class,
4050 int length) { 4006 intptr_t length) {
4051 length--; // Remove final 0x10000. 4007 length--; // Remove final 0x10000.
4052 DCHECK(special_class[length] == 0x10000); 4008 ASSERT(special_class[length] == 0x10000);
4053 if (ranges->length() * 2 != length) { 4009 if (ranges->length() * 2 != length) {
4054 return false; 4010 return false;
4055 } 4011 }
4056 for (int i = 0; i < length; i += 2) { 4012 for (intptr_t i = 0; i < length; i += 2) {
4057 CharacterRange range = ranges->at(i >> 1); 4013 CharacterRange range = ranges->At(i >> 1);
4058 if (range.from() != special_class[i] || 4014 if (range.from() != special_class[i] ||
4059 range.to() != special_class[i + 1] - 1) { 4015 range.to() != special_class[i + 1] - 1) {
4060 return false; 4016 return false;
4061 } 4017 }
4062 } 4018 }
4063 return true; 4019 return true;
4064 } 4020 }
4065 4021
4066 4022
4067 bool RegExpCharacterClass::is_standard(Zone* zone) { 4023 bool RegExpCharacterClass::is_standard() {
4068 // TODO(lrn): Remove need for this function, by not throwing away information 4024 // TODO(lrn): Remove need for this function, by not throwing away information
4069 // along the way. 4025 // along the way.
4070 if (is_negated_) { 4026 if (is_negated_) {
4071 return false; 4027 return false;
4072 } 4028 }
4073 if (set_.is_standard()) { 4029 if (set_.is_standard()) {
4074 return true; 4030 return true;
4075 } 4031 }
4076 if (CompareRanges(set_.ranges(zone), kSpaceRanges, kSpaceRangeCount)) { 4032 if (CompareRanges(set_.ranges(), kSpaceRanges, kSpaceRangeCount)) {
4077 set_.set_standard_set_type('s'); 4033 set_.set_standard_set_type('s');
4078 return true; 4034 return true;
4079 } 4035 }
4080 if (CompareInverseRanges(set_.ranges(zone), kSpaceRanges, kSpaceRangeCount)) { 4036 if (CompareInverseRanges(set_.ranges(), kSpaceRanges, kSpaceRangeCount)) {
4081 set_.set_standard_set_type('S'); 4037 set_.set_standard_set_type('S');
4082 return true; 4038 return true;
4083 } 4039 }
4084 if (CompareInverseRanges(set_.ranges(zone), 4040 if (CompareInverseRanges(set_.ranges(),
4085 kLineTerminatorRanges, 4041 kLineTerminatorRanges,
4086 kLineTerminatorRangeCount)) { 4042 kLineTerminatorRangeCount)) {
4087 set_.set_standard_set_type('.'); 4043 set_.set_standard_set_type('.');
4088 return true; 4044 return true;
4089 } 4045 }
4090 if (CompareRanges(set_.ranges(zone), 4046 if (CompareRanges(set_.ranges(),
4091 kLineTerminatorRanges, 4047 kLineTerminatorRanges,
4092 kLineTerminatorRangeCount)) { 4048 kLineTerminatorRangeCount)) {
4093 set_.set_standard_set_type('n'); 4049 set_.set_standard_set_type('n');
4094 return true; 4050 return true;
4095 } 4051 }
4096 if (CompareRanges(set_.ranges(zone), kWordRanges, kWordRangeCount)) { 4052 if (CompareRanges(set_.ranges(), kWordRanges, kWordRangeCount)) {
4097 set_.set_standard_set_type('w'); 4053 set_.set_standard_set_type('w');
4098 return true; 4054 return true;
4099 } 4055 }
4100 if (CompareInverseRanges(set_.ranges(zone), kWordRanges, kWordRangeCount)) { 4056 if (CompareInverseRanges(set_.ranges(), kWordRanges, kWordRangeCount)) {
4101 set_.set_standard_set_type('W'); 4057 set_.set_standard_set_type('W');
4102 return true; 4058 return true;
4103 } 4059 }
4104 return false; 4060 return false;
4105 } 4061 }
4106 4062
4107 4063
4108 RegExpNode* RegExpCharacterClass::ToNode(RegExpCompiler* compiler, 4064 RegExpNode* RegExpCharacterClass::ToNode(RegExpCompiler* compiler,
4109 RegExpNode* on_success) { 4065 RegExpNode* on_success) {
4110 return new(compiler->zone()) TextNode(this, on_success); 4066 return new(CI) TextNode(this, on_success);
4111 } 4067 }
4112 4068
4113 4069
4114 RegExpNode* RegExpDisjunction::ToNode(RegExpCompiler* compiler, 4070 RegExpNode* RegExpDisjunction::ToNode(RegExpCompiler* compiler,
4115 RegExpNode* on_success) { 4071 RegExpNode* on_success) {
4116 ZoneList<RegExpTree*>* alternatives = this->alternatives(); 4072 ZoneGrowableArray<RegExpTree*>* alternatives = this->alternatives();
4117 int length = alternatives->length(); 4073 intptr_t length = alternatives->length();
4118 ChoiceNode* result = 4074 ChoiceNode* result =
4119 new(compiler->zone()) ChoiceNode(length, compiler->zone()); 4075 new(CI) ChoiceNode(length, CI);
4120 for (int i = 0; i < length; i++) { 4076 for (intptr_t i = 0; i < length; i++) {
4121 GuardedAlternative alternative(alternatives->at(i)->ToNode(compiler, 4077 GuardedAlternative alternative(alternatives->At(i)->ToNode(compiler,
4122 on_success)); 4078 on_success));
4123 result->AddAlternative(alternative); 4079 result->AddAlternative(alternative);
4124 } 4080 }
4125 return result; 4081 return result;
4126 } 4082 }
4127 4083
4128 4084
4129 RegExpNode* RegExpQuantifier::ToNode(RegExpCompiler* compiler, 4085 RegExpNode* RegExpQuantifier::ToNode(RegExpCompiler* compiler,
4130 RegExpNode* on_success) { 4086 RegExpNode* on_success) {
4131 return ToNode(min(), 4087 return ToNode(min(),
4132 max(), 4088 max(),
4133 is_greedy(), 4089 is_greedy(),
4134 body(), 4090 body(),
4135 compiler, 4091 compiler,
4136 on_success); 4092 on_success);
4137 } 4093 }
4138 4094
4139 4095
4140 // Scoped object to keep track of how much we unroll quantifier loops in the 4096 // Scoped object to keep track of how much we unroll quantifier loops in the
4141 // regexp graph generator. 4097 // regexp graph generator.
4142 class RegExpExpansionLimiter { 4098 class RegExpExpansionLimiter : public ValueObject {
4143 public: 4099 public:
4144 static const int kMaxExpansionFactor = 6; 4100 static const intptr_t kMaxExpansionFactor = 6;
4145 RegExpExpansionLimiter(RegExpCompiler* compiler, int factor) 4101 RegExpExpansionLimiter(RegExpCompiler* compiler, intptr_t factor)
4146 : compiler_(compiler), 4102 : compiler_(compiler),
4147 saved_expansion_factor_(compiler->current_expansion_factor()), 4103 saved_expansion_factor_(compiler->current_expansion_factor()),
4148 ok_to_expand_(saved_expansion_factor_ <= kMaxExpansionFactor) { 4104 ok_to_expand_(saved_expansion_factor_ <= kMaxExpansionFactor) {
4149 DCHECK(factor > 0); 4105 ASSERT(factor > 0);
4150 if (ok_to_expand_) { 4106 if (ok_to_expand_) {
4151 if (factor > kMaxExpansionFactor) { 4107 if (factor > kMaxExpansionFactor) {
4152 // Avoid integer overflow of the current expansion factor. 4108 // Avoid integer overflow of the current expansion factor.
4153 ok_to_expand_ = false; 4109 ok_to_expand_ = false;
4154 compiler->set_current_expansion_factor(kMaxExpansionFactor + 1); 4110 compiler->set_current_expansion_factor(kMaxExpansionFactor + 1);
4155 } else { 4111 } else {
4156 int new_factor = saved_expansion_factor_ * factor; 4112 intptr_t new_factor = saved_expansion_factor_ * factor;
4157 ok_to_expand_ = (new_factor <= kMaxExpansionFactor); 4113 ok_to_expand_ = (new_factor <= kMaxExpansionFactor);
4158 compiler->set_current_expansion_factor(new_factor); 4114 compiler->set_current_expansion_factor(new_factor);
4159 } 4115 }
4160 } 4116 }
4161 } 4117 }
4162 4118
4163 ~RegExpExpansionLimiter() { 4119 ~RegExpExpansionLimiter() {
4164 compiler_->set_current_expansion_factor(saved_expansion_factor_); 4120 compiler_->set_current_expansion_factor(saved_expansion_factor_);
4165 } 4121 }
4166 4122
4167 bool ok_to_expand() { return ok_to_expand_; } 4123 bool ok_to_expand() { return ok_to_expand_; }
4168 4124
4169 private: 4125 private:
4170 RegExpCompiler* compiler_; 4126 RegExpCompiler* compiler_;
4171 int saved_expansion_factor_; 4127 intptr_t saved_expansion_factor_;
4172 bool ok_to_expand_; 4128 bool ok_to_expand_;
4173 4129
4174 DISALLOW_IMPLICIT_CONSTRUCTORS(RegExpExpansionLimiter); 4130 DISALLOW_IMPLICIT_CONSTRUCTORS(RegExpExpansionLimiter);
4175 }; 4131 };
4176 4132
4177 4133
4178 RegExpNode* RegExpQuantifier::ToNode(int min, 4134 RegExpNode* RegExpQuantifier::ToNode(intptr_t min,
4179 int max, 4135 intptr_t max,
4180 bool is_greedy, 4136 bool is_greedy,
4181 RegExpTree* body, 4137 RegExpTree* body,
4182 RegExpCompiler* compiler, 4138 RegExpCompiler* compiler,
4183 RegExpNode* on_success, 4139 RegExpNode* on_success,
4184 bool not_at_start) { 4140 bool not_at_start) {
4185 // x{f, t} becomes this: 4141 // x{f, t} becomes this:
4186 // 4142 //
4187 // (r++)<-. 4143 // (r++)<-.
4188 // | ` 4144 // | `
4189 // | (x) 4145 // | (x)
4190 // v ^ 4146 // v ^
4191 // (r=0)-->(?)---/ [if r < t] 4147 // (r=0)-->(?)---/ [if r < t]
4192 // | 4148 // |
4193 // [if r >= f] \----> ... 4149 // [if r >= f] \----> ...
4194 // 4150 //
4195 4151
4196 // 15.10.2.5 RepeatMatcher algorithm. 4152 // 15.10.2.5 RepeatMatcher algorithm.
4197 // The parser has already eliminated the case where max is 0. In the case 4153 // The parser has already eliminated the case where max is 0. In the case
4198 // where max_match is zero the parser has removed the quantifier if min was 4154 // where max_match is zero the parser has removed the quantifier if min was
4199 // > 0 and removed the atom if min was 0. See AddQuantifierToAtom. 4155 // > 0 and removed the atom if min was 0. See AddQuantifierToAtom.
4200 4156
4201 // If we know that we cannot match zero length then things are a little 4157 // If we know that we cannot match zero length then things are a little
4202 // simpler since we don't need to make the special zero length match check 4158 // simpler since we don't need to make the special zero length match check
4203 // from step 2.1. If the min and max are small we can unroll a little in 4159 // from step 2.1. If the min and max are small we can unroll a little in
4204 // this case. 4160 // this case.
4205 static const int kMaxUnrolledMinMatches = 3; // Unroll (foo)+ and (foo){3,} 4161 // Unroll (foo)+ and (foo){3,}
4206 static const int kMaxUnrolledMaxMatches = 3; // Unroll (foo)? and (foo){x,3} 4162 static const intptr_t kMaxUnrolledMinMatches = 3;
4163 // Unroll (foo)? and (foo){x,3}
4164 static const intptr_t kMaxUnrolledMaxMatches = 3;
4207 if (max == 0) return on_success; // This can happen due to recursion. 4165 if (max == 0) return on_success; // This can happen due to recursion.
4208 bool body_can_be_empty = (body->min_match() == 0); 4166 bool body_can_be_empty = (body->min_match() == 0);
4209 int body_start_reg = RegExpCompiler::kNoRegister; 4167 intptr_t body_start_reg = RegExpCompiler::kNoRegister;
4210 Interval capture_registers = body->CaptureRegisters(); 4168 Interval capture_registers = body->CaptureRegisters();
4211 bool needs_capture_clearing = !capture_registers.is_empty(); 4169 bool needs_capture_clearing = !capture_registers.is_empty();
4212 Zone* zone = compiler->zone(); 4170 Isolate* isolate = compiler->isolate();
4213 4171
4214 if (body_can_be_empty) { 4172 if (body_can_be_empty) {
4215 body_start_reg = compiler->AllocateRegister(); 4173 body_start_reg = compiler->AllocateRegister();
4216 } else if (FLAG_regexp_optimization && !needs_capture_clearing) { 4174 } else if (kRegexpOptimization && !needs_capture_clearing) {
4217 // Only unroll if there are no captures and the body can't be 4175 // Only unroll if there are no captures and the body can't be
4218 // empty. 4176 // empty.
4219 { 4177 {
4220 RegExpExpansionLimiter limiter( 4178 RegExpExpansionLimiter limiter(
4221 compiler, min + ((max != min) ? 1 : 0)); 4179 compiler, min + ((max != min) ? 1 : 0));
4222 if (min > 0 && min <= kMaxUnrolledMinMatches && limiter.ok_to_expand()) { 4180 if (min > 0 && min <= kMaxUnrolledMinMatches && limiter.ok_to_expand()) {
4223 int new_max = (max == kInfinity) ? max : max - min; 4181 intptr_t new_max = (max == kInfinity) ? max : max - min;
4224 // Recurse once to get the loop or optional matches after the fixed 4182 // Recurse once to get the loop or optional matches after the fixed
4225 // ones. 4183 // ones.
4226 RegExpNode* answer = ToNode( 4184 RegExpNode* answer = ToNode(
4227 0, new_max, is_greedy, body, compiler, on_success, true); 4185 0, new_max, is_greedy, body, compiler, on_success, true);
4228 // Unroll the forced matches from 0 to min. This can cause chains of 4186 // Unroll the forced matches from 0 to min. This can cause chains of
4229 // TextNodes (which the parser does not generate). These should be 4187 // TextNodes (which the parser does not generate). These should be
4230 // combined if it turns out they hinder good code generation. 4188 // combined if it turns out they hinder good code generation.
4231 for (int i = 0; i < min; i++) { 4189 for (intptr_t i = 0; i < min; i++) {
4232 answer = body->ToNode(compiler, answer); 4190 answer = body->ToNode(compiler, answer);
4233 } 4191 }
4234 return answer; 4192 return answer;
4235 } 4193 }
4236 } 4194 }
4237 if (max <= kMaxUnrolledMaxMatches && min == 0) { 4195 if (max <= kMaxUnrolledMaxMatches && min == 0) {
4238 DCHECK(max > 0); // Due to the 'if' above. 4196 ASSERT(max > 0); // Due to the 'if' above.
4239 RegExpExpansionLimiter limiter(compiler, max); 4197 RegExpExpansionLimiter limiter(compiler, max);
4240 if (limiter.ok_to_expand()) { 4198 if (limiter.ok_to_expand()) {
4241 // Unroll the optional matches up to max. 4199 // Unroll the optional matches up to max.
4242 RegExpNode* answer = on_success; 4200 RegExpNode* answer = on_success;
4243 for (int i = 0; i < max; i++) { 4201 for (intptr_t i = 0; i < max; i++) {
4244 ChoiceNode* alternation = new(zone) ChoiceNode(2, zone); 4202 ChoiceNode* alternation = new(isolate) ChoiceNode(2, isolate);
4245 if (is_greedy) { 4203 if (is_greedy) {
4246 alternation->AddAlternative( 4204 alternation->AddAlternative(
4247 GuardedAlternative(body->ToNode(compiler, answer))); 4205 GuardedAlternative(body->ToNode(compiler, answer)));
4248 alternation->AddAlternative(GuardedAlternative(on_success)); 4206 alternation->AddAlternative(GuardedAlternative(on_success));
4249 } else { 4207 } else {
4250 alternation->AddAlternative(GuardedAlternative(on_success)); 4208 alternation->AddAlternative(GuardedAlternative(on_success));
4251 alternation->AddAlternative( 4209 alternation->AddAlternative(
4252 GuardedAlternative(body->ToNode(compiler, answer))); 4210 GuardedAlternative(body->ToNode(compiler, answer)));
4253 } 4211 }
4254 answer = alternation; 4212 answer = alternation;
4255 if (not_at_start) alternation->set_not_at_start(); 4213 if (not_at_start) alternation->set_not_at_start();
4256 } 4214 }
4257 return answer; 4215 return answer;
4258 } 4216 }
4259 } 4217 }
4260 } 4218 }
4261 bool has_min = min > 0; 4219 bool has_min = min > 0;
4262 bool has_max = max < RegExpTree::kInfinity; 4220 bool has_max = max < RegExpTree::kInfinity;
4263 bool needs_counter = has_min || has_max; 4221 bool needs_counter = has_min || has_max;
4264 int reg_ctr = needs_counter 4222 intptr_t reg_ctr = needs_counter
4265 ? compiler->AllocateRegister() 4223 ? compiler->AllocateRegister()
4266 : RegExpCompiler::kNoRegister; 4224 : RegExpCompiler::kNoRegister;
4267 LoopChoiceNode* center = new(zone) LoopChoiceNode(body->min_match() == 0, 4225 LoopChoiceNode* center = new(isolate) LoopChoiceNode(body->min_match() == 0,
4268 zone); 4226 isolate);
4269 if (not_at_start) center->set_not_at_start(); 4227 if (not_at_start) center->set_not_at_start();
4270 RegExpNode* loop_return = needs_counter 4228 RegExpNode* loop_return = needs_counter
4271 ? static_cast<RegExpNode*>(ActionNode::IncrementRegister(reg_ctr, center)) 4229 ? static_cast<RegExpNode*>(ActionNode::IncrementRegister(reg_ctr, center))
4272 : static_cast<RegExpNode*>(center); 4230 : static_cast<RegExpNode*>(center);
4273 if (body_can_be_empty) { 4231 if (body_can_be_empty) {
4274 // If the body can be empty we need to check if it was and then 4232 // If the body can be empty we need to check if it was and then
4275 // backtrack. 4233 // backtrack.
4276 loop_return = ActionNode::EmptyMatchCheck(body_start_reg, 4234 loop_return = ActionNode::EmptyMatchCheck(body_start_reg,
4277 reg_ctr, 4235 reg_ctr,
4278 min, 4236 min,
4279 loop_return); 4237 loop_return);
4280 } 4238 }
4281 RegExpNode* body_node = body->ToNode(compiler, loop_return); 4239 RegExpNode* body_node = body->ToNode(compiler, loop_return);
4282 if (body_can_be_empty) { 4240 if (body_can_be_empty) {
4283 // If the body can be empty we need to store the start position 4241 // If the body can be empty we need to store the start position
4284 // so we can bail out if it was empty. 4242 // so we can bail out if it was empty.
4285 body_node = ActionNode::StorePosition(body_start_reg, false, body_node); 4243 body_node = ActionNode::StorePosition(body_start_reg, false, body_node);
4286 } 4244 }
4287 if (needs_capture_clearing) { 4245 if (needs_capture_clearing) {
4288 // Before entering the body of this loop we need to clear captures. 4246 // Before entering the body of this loop we need to clear captures.
4289 body_node = ActionNode::ClearCaptures(capture_registers, body_node); 4247 body_node = ActionNode::ClearCaptures(capture_registers, body_node);
4290 } 4248 }
4291 GuardedAlternative body_alt(body_node); 4249 GuardedAlternative body_alt(body_node);
4292 if (has_max) { 4250 if (has_max) {
4293 Guard* body_guard = 4251 Guard* body_guard =
4294 new(zone) Guard(reg_ctr, Guard::LT, max); 4252 new(isolate) Guard(reg_ctr, Guard::LT, max);
4295 body_alt.AddGuard(body_guard, zone); 4253 body_alt.AddGuard(body_guard, isolate);
4296 } 4254 }
4297 GuardedAlternative rest_alt(on_success); 4255 GuardedAlternative rest_alt(on_success);
4298 if (has_min) { 4256 if (has_min) {
4299 Guard* rest_guard = new(compiler->zone()) Guard(reg_ctr, Guard::GEQ, min); 4257 Guard* rest_guard = new(isolate) Guard(reg_ctr, Guard::GEQ, min);
4300 rest_alt.AddGuard(rest_guard, zone); 4258 rest_alt.AddGuard(rest_guard, isolate);
4301 } 4259 }
4302 if (is_greedy) { 4260 if (is_greedy) {
4303 center->AddLoopAlternative(body_alt); 4261 center->AddLoopAlternative(body_alt);
4304 center->AddContinueAlternative(rest_alt); 4262 center->AddContinueAlternative(rest_alt);
4305 } else { 4263 } else {
4306 center->AddContinueAlternative(rest_alt); 4264 center->AddContinueAlternative(rest_alt);
4307 center->AddLoopAlternative(body_alt); 4265 center->AddLoopAlternative(body_alt);
4308 } 4266 }
4309 if (needs_counter) { 4267 if (needs_counter) {
4310 return ActionNode::SetRegister(reg_ctr, 0, center); 4268 return ActionNode::SetRegister(reg_ctr, 0, center);
4311 } else { 4269 } else {
4312 return center; 4270 return center;
4313 } 4271 }
4314 } 4272 }
4315 4273
4316 4274
4317 RegExpNode* RegExpAssertion::ToNode(RegExpCompiler* compiler, 4275 RegExpNode* RegExpAssertion::ToNode(RegExpCompiler* compiler,
4318 RegExpNode* on_success) { 4276 RegExpNode* on_success) {
4319 NodeInfo info;
4320 Zone* zone = compiler->zone();
4321
4322 switch (assertion_type()) { 4277 switch (assertion_type()) {
4323 case START_OF_LINE: 4278 case START_OF_LINE:
4324 return AssertionNode::AfterNewline(on_success); 4279 return AssertionNode::AfterNewline(on_success);
4325 case START_OF_INPUT: 4280 case START_OF_INPUT:
4326 return AssertionNode::AtStart(on_success); 4281 return AssertionNode::AtStart(on_success);
4327 case BOUNDARY: 4282 case BOUNDARY:
4328 return AssertionNode::AtBoundary(on_success); 4283 return AssertionNode::AtBoundary(on_success);
4329 case NON_BOUNDARY: 4284 case NON_BOUNDARY:
4330 return AssertionNode::AtNonBoundary(on_success); 4285 return AssertionNode::AtNonBoundary(on_success);
4331 case END_OF_INPUT: 4286 case END_OF_INPUT:
4332 return AssertionNode::AtEnd(on_success); 4287 return AssertionNode::AtEnd(on_success);
4333 case END_OF_LINE: { 4288 case END_OF_LINE: {
4334 // Compile $ in multiline regexps as an alternation with a positive 4289 // Compile $ in multiline regexps as an alternation with a positive
4335 // lookahead in one side and an end-of-input on the other side. 4290 // lookahead in one side and an end-of-input on the other side.
4336 // We need two registers for the lookahead. 4291 // We need two registers for the lookahead.
4337 int stack_pointer_register = compiler->AllocateRegister(); 4292 intptr_t stack_pointer_register = compiler->AllocateRegister();
4338 int position_register = compiler->AllocateRegister(); 4293 intptr_t position_register = compiler->AllocateRegister();
4339 // The ChoiceNode to distinguish between a newline and end-of-input. 4294 // The ChoiceNode to distinguish between a newline and end-of-input.
4340 ChoiceNode* result = new(zone) ChoiceNode(2, zone); 4295 ChoiceNode* result = new ChoiceNode(2, on_success->isolate());
4341 // Create a newline atom. 4296 // Create a newline atom.
4342 ZoneList<CharacterRange>* newline_ranges = 4297 ZoneGrowableArray<CharacterRange>* newline_ranges =
4343 new(zone) ZoneList<CharacterRange>(3, zone); 4298 new ZoneGrowableArray<CharacterRange>(3);
4344 CharacterRange::AddClassEscape('n', newline_ranges, zone); 4299 CharacterRange::AddClassEscape('n', newline_ranges);
4345 RegExpCharacterClass* newline_atom = new(zone) RegExpCharacterClass('n'); 4300 RegExpCharacterClass* newline_atom = new RegExpCharacterClass('n');
4346 TextNode* newline_matcher = new(zone) TextNode( 4301 TextNode* newline_matcher = new TextNode(
4347 newline_atom, 4302 newline_atom,
4348 ActionNode::PositiveSubmatchSuccess(stack_pointer_register, 4303 ActionNode::PositiveSubmatchSuccess(stack_pointer_register,
4349 position_register, 4304 position_register,
4350 0, // No captures inside. 4305 0, // No captures inside.
4351 -1, // Ignored if no captures. 4306 -1, // Ignored if no captures.
4352 on_success)); 4307 on_success));
4353 // Create an end-of-input matcher. 4308 // Create an end-of-input matcher.
4354 RegExpNode* end_of_line = ActionNode::BeginSubmatch( 4309 RegExpNode* end_of_line = ActionNode::BeginSubmatch(
4355 stack_pointer_register, 4310 stack_pointer_register,
4356 position_register, 4311 position_register,
4357 newline_matcher); 4312 newline_matcher);
4358 // Add the two alternatives to the ChoiceNode. 4313 // Add the two alternatives to the ChoiceNode.
4359 GuardedAlternative eol_alternative(end_of_line); 4314 GuardedAlternative eol_alternative(end_of_line);
4360 result->AddAlternative(eol_alternative); 4315 result->AddAlternative(eol_alternative);
4361 GuardedAlternative end_alternative(AssertionNode::AtEnd(on_success)); 4316 GuardedAlternative end_alternative(AssertionNode::AtEnd(on_success));
4362 result->AddAlternative(end_alternative); 4317 result->AddAlternative(end_alternative);
4363 return result; 4318 return result;
4364 } 4319 }
4365 default: 4320 default:
4366 UNREACHABLE(); 4321 UNREACHABLE();
4367 } 4322 }
4368 return on_success; 4323 return on_success;
4369 } 4324 }
4370 4325
4371 4326
4372 RegExpNode* RegExpBackReference::ToNode(RegExpCompiler* compiler, 4327 RegExpNode* RegExpBackReference::ToNode(RegExpCompiler* compiler,
4373 RegExpNode* on_success) { 4328 RegExpNode* on_success) {
4374 return new(compiler->zone()) 4329 return new(CI)
4375 BackReferenceNode(RegExpCapture::StartRegister(index()), 4330 BackReferenceNode(RegExpCapture::StartRegister(index()),
4376 RegExpCapture::EndRegister(index()), 4331 RegExpCapture::EndRegister(index()),
4377 on_success); 4332 on_success);
4378 } 4333 }
4379 4334
4380 4335
4381 RegExpNode* RegExpEmpty::ToNode(RegExpCompiler* compiler, 4336 RegExpNode* RegExpEmpty::ToNode(RegExpCompiler* compiler,
4382 RegExpNode* on_success) { 4337 RegExpNode* on_success) {
4383 return on_success; 4338 return on_success;
4384 } 4339 }
4385 4340
4386 4341
4387 RegExpNode* RegExpLookahead::ToNode(RegExpCompiler* compiler, 4342 RegExpNode* RegExpLookahead::ToNode(RegExpCompiler* compiler,
4388 RegExpNode* on_success) { 4343 RegExpNode* on_success) {
4389 int stack_pointer_register = compiler->AllocateRegister(); 4344 intptr_t stack_pointer_register = compiler->AllocateRegister();
4390 int position_register = compiler->AllocateRegister(); 4345 intptr_t position_register = compiler->AllocateRegister();
4391 4346
4392 const int registers_per_capture = 2; 4347 const intptr_t registers_per_capture = 2;
4393 const int register_of_first_capture = 2; 4348 const intptr_t register_of_first_capture = 2;
4394 int register_count = capture_count_ * registers_per_capture; 4349 intptr_t register_count = capture_count_ * registers_per_capture;
4395 int register_start = 4350 intptr_t register_start =
4396 register_of_first_capture + capture_from_ * registers_per_capture; 4351 register_of_first_capture + capture_from_ * registers_per_capture;
4397 4352
4398 RegExpNode* success; 4353 RegExpNode* success;
4399 if (is_positive()) { 4354 if (is_positive()) {
4400 RegExpNode* node = ActionNode::BeginSubmatch( 4355 RegExpNode* node = ActionNode::BeginSubmatch(
4401 stack_pointer_register, 4356 stack_pointer_register,
4402 position_register, 4357 position_register,
4403 body()->ToNode( 4358 body()->ToNode(
4404 compiler, 4359 compiler,
4405 ActionNode::PositiveSubmatchSuccess(stack_pointer_register, 4360 ActionNode::PositiveSubmatchSuccess(stack_pointer_register,
4406 position_register, 4361 position_register,
4407 register_count, 4362 register_count,
4408 register_start, 4363 register_start,
4409 on_success))); 4364 on_success)));
4410 return node; 4365 return node;
4411 } else { 4366 } else {
4412 // We use a ChoiceNode for a negative lookahead because it has most of 4367 // We use a ChoiceNode for a negative lookahead because it has most of
4413 // the characteristics we need. It has the body of the lookahead as its 4368 // the characteristics we need. It has the body of the lookahead as its
4414 // first alternative and the expression after the lookahead of the second 4369 // first alternative and the expression after the lookahead of the second
4415 // alternative. If the first alternative succeeds then the 4370 // alternative. If the first alternative succeeds then the
4416 // NegativeSubmatchSuccess will unwind the stack including everything the 4371 // NegativeSubmatchSuccess will unwind the stack including everything the
4417 // choice node set up and backtrack. If the first alternative fails then 4372 // choice node set up and backtrack. If the first alternative fails then
4418 // the second alternative is tried, which is exactly the desired result 4373 // the second alternative is tried, which is exactly the desired result
4419 // for a negative lookahead. The NegativeLookaheadChoiceNode is a special 4374 // for a negative lookahead. The NegativeLookaheadChoiceNode is a special
4420 // ChoiceNode that knows to ignore the first exit when calculating quick 4375 // ChoiceNode that knows to ignore the first exit when calculating quick
4421 // checks. 4376 // checks.
4422 Zone* zone = compiler->zone();
4423 4377
4424 GuardedAlternative body_alt( 4378 GuardedAlternative body_alt(
4425 body()->ToNode( 4379 body()->ToNode(
4426 compiler, 4380 compiler,
4427 success = new(zone) NegativeSubmatchSuccess(stack_pointer_register, 4381 success = new(CI) NegativeSubmatchSuccess(stack_pointer_register,
4428 position_register, 4382 position_register,
4429 register_count, 4383 register_count,
4430 register_start, 4384 register_start,
4431 zone))); 4385 CI)));
4432 ChoiceNode* choice_node = 4386 ChoiceNode* choice_node =
4433 new(zone) NegativeLookaheadChoiceNode(body_alt, 4387 new(CI) NegativeLookaheadChoiceNode(body_alt,
4434 GuardedAlternative(on_success), 4388 GuardedAlternative(on_success),
4435 zone); 4389 CI);
4436 return ActionNode::BeginSubmatch(stack_pointer_register, 4390 return ActionNode::BeginSubmatch(stack_pointer_register,
4437 position_register, 4391 position_register,
4438 choice_node); 4392 choice_node);
4439 } 4393 }
4440 } 4394 }
4441 4395
4442 4396
4443 RegExpNode* RegExpCapture::ToNode(RegExpCompiler* compiler, 4397 RegExpNode* RegExpCapture::ToNode(RegExpCompiler* compiler,
4444 RegExpNode* on_success) { 4398 RegExpNode* on_success) {
4445 return ToNode(body(), index(), compiler, on_success); 4399 return ToNode(body(), index(), compiler, on_success);
4446 } 4400 }
4447 4401
4448 4402
4449 RegExpNode* RegExpCapture::ToNode(RegExpTree* body, 4403 RegExpNode* RegExpCapture::ToNode(RegExpTree* body,
4450 int index, 4404 intptr_t index,
4451 RegExpCompiler* compiler, 4405 RegExpCompiler* compiler,
4452 RegExpNode* on_success) { 4406 RegExpNode* on_success) {
4453 int start_reg = RegExpCapture::StartRegister(index); 4407 intptr_t start_reg = RegExpCapture::StartRegister(index);
4454 int end_reg = RegExpCapture::EndRegister(index); 4408 intptr_t end_reg = RegExpCapture::EndRegister(index);
4455 RegExpNode* store_end = ActionNode::StorePosition(end_reg, true, on_success); 4409 RegExpNode* store_end = ActionNode::StorePosition(end_reg, true, on_success);
4456 RegExpNode* body_node = body->ToNode(compiler, store_end); 4410 RegExpNode* body_node = body->ToNode(compiler, store_end);
4457 return ActionNode::StorePosition(start_reg, true, body_node); 4411 return ActionNode::StorePosition(start_reg, true, body_node);
4458 } 4412 }
4459 4413
4460 4414
4461 RegExpNode* RegExpAlternative::ToNode(RegExpCompiler* compiler, 4415 RegExpNode* RegExpAlternative::ToNode(RegExpCompiler* compiler,
4462 RegExpNode* on_success) { 4416 RegExpNode* on_success) {
4463 ZoneList<RegExpTree*>* children = nodes(); 4417 ZoneGrowableArray<RegExpTree*>* children = nodes();
4464 RegExpNode* current = on_success; 4418 RegExpNode* current = on_success;
4465 for (int i = children->length() - 1; i >= 0; i--) { 4419 for (intptr_t i = children->length() - 1; i >= 0; i--) {
4466 current = children->at(i)->ToNode(compiler, current); 4420 current = children->At(i)->ToNode(compiler, current);
4467 } 4421 }
4468 return current; 4422 return current;
4469 } 4423 }
4470 4424
4471 4425
4472 static void AddClass(const int* elmv, 4426 static void AddClass(const intptr_t* elmv,
4473 int elmc, 4427 intptr_t elmc,
4474 ZoneList<CharacterRange>* ranges, 4428 ZoneGrowableArray<CharacterRange>* ranges) {
4475 Zone* zone) {
4476 elmc--; 4429 elmc--;
4477 DCHECK(elmv[elmc] == 0x10000); 4430 ASSERT(elmv[elmc] == 0x10000);
4478 for (int i = 0; i < elmc; i += 2) { 4431 for (intptr_t i = 0; i < elmc; i += 2) {
4479 DCHECK(elmv[i] < elmv[i + 1]); 4432 ASSERT(elmv[i] < elmv[i + 1]);
4480 ranges->Add(CharacterRange(elmv[i], elmv[i + 1] - 1), zone); 4433 ranges->Add(CharacterRange(elmv[i], elmv[i + 1] - 1));
4481 } 4434 }
4482 } 4435 }
4483 4436
4484 4437
4485 static void AddClassNegated(const int *elmv, 4438 static void AddClassNegated(const intptr_t *elmv,
4486 int elmc, 4439 intptr_t elmc,
4487 ZoneList<CharacterRange>* ranges, 4440 ZoneGrowableArray<CharacterRange>* ranges) {
4488 Zone* zone) {
4489 elmc--; 4441 elmc--;
4490 DCHECK(elmv[elmc] == 0x10000); 4442 ASSERT(elmv[elmc] == 0x10000);
4491 DCHECK(elmv[0] != 0x0000); 4443 ASSERT(elmv[0] != 0x0000);
4492 DCHECK(elmv[elmc-1] != String::kMaxUtf16CodeUnit); 4444 ASSERT(elmv[elmc-1] != Utf16::kMaxCodeUnit);
4493 uc16 last = 0x0000; 4445 uint16_t last = 0x0000;
4494 for (int i = 0; i < elmc; i += 2) { 4446 for (intptr_t i = 0; i < elmc; i += 2) {
4495 DCHECK(last <= elmv[i] - 1); 4447 ASSERT(last <= elmv[i] - 1);
4496 DCHECK(elmv[i] < elmv[i + 1]); 4448 ASSERT(elmv[i] < elmv[i + 1]);
4497 ranges->Add(CharacterRange(last, elmv[i] - 1), zone); 4449 ranges->Add(CharacterRange(last, elmv[i] - 1));
4498 last = elmv[i + 1]; 4450 last = elmv[i + 1];
4499 } 4451 }
4500 ranges->Add(CharacterRange(last, String::kMaxUtf16CodeUnit), zone); 4452 ranges->Add(CharacterRange(last, Utf16::kMaxCodeUnit));
4501 } 4453 }
4502 4454
4503 4455
4504 void CharacterRange::AddClassEscape(uc16 type, 4456 void CharacterRange::AddClassEscape(uint16_t type,
4505 ZoneList<CharacterRange>* ranges, 4457 ZoneGrowableArray<CharacterRange>* ranges) {
4506 Zone* zone) {
4507 switch (type) { 4458 switch (type) {
4508 case 's': 4459 case 's':
4509 AddClass(kSpaceRanges, kSpaceRangeCount, ranges, zone); 4460 AddClass(kSpaceRanges, kSpaceRangeCount, ranges);
4510 break; 4461 break;
4511 case 'S': 4462 case 'S':
4512 AddClassNegated(kSpaceRanges, kSpaceRangeCount, ranges, zone); 4463 AddClassNegated(kSpaceRanges, kSpaceRangeCount, ranges);
4513 break; 4464 break;
4514 case 'w': 4465 case 'w':
4515 AddClass(kWordRanges, kWordRangeCount, ranges, zone); 4466 AddClass(kWordRanges, kWordRangeCount, ranges);
4516 break; 4467 break;
4517 case 'W': 4468 case 'W':
4518 AddClassNegated(kWordRanges, kWordRangeCount, ranges, zone); 4469 AddClassNegated(kWordRanges, kWordRangeCount, ranges);
4519 break; 4470 break;
4520 case 'd': 4471 case 'd':
4521 AddClass(kDigitRanges, kDigitRangeCount, ranges, zone); 4472 AddClass(kDigitRanges, kDigitRangeCount, ranges);
4522 break; 4473 break;
4523 case 'D': 4474 case 'D':
4524 AddClassNegated(kDigitRanges, kDigitRangeCount, ranges, zone); 4475 AddClassNegated(kDigitRanges, kDigitRangeCount, ranges);
4525 break; 4476 break;
4526 case '.': 4477 case '.':
4527 AddClassNegated(kLineTerminatorRanges, 4478 AddClassNegated(kLineTerminatorRanges,
4528 kLineTerminatorRangeCount, 4479 kLineTerminatorRangeCount,
4529 ranges, 4480 ranges);
4530 zone);
4531 break; 4481 break;
4532 // This is not a character range as defined by the spec but a 4482 // This is not a character range as defined by the spec but a
4533 // convenient shorthand for a character class that matches any 4483 // convenient shorthand for a character class that matches any
4534 // character. 4484 // character.
4535 case '*': 4485 case '*':
4536 ranges->Add(CharacterRange::Everything(), zone); 4486 ranges->Add(CharacterRange::Everything());
4537 break; 4487 break;
4538 // This is the set of characters matched by the $ and ^ symbols 4488 // This is the set of characters matched by the $ and ^ symbols
4539 // in multiline mode. 4489 // in multiline mode.
4540 case 'n': 4490 case 'n':
4541 AddClass(kLineTerminatorRanges, 4491 AddClass(kLineTerminatorRanges,
4542 kLineTerminatorRangeCount, 4492 kLineTerminatorRangeCount,
4543 ranges, 4493 ranges);
4544 zone);
4545 break; 4494 break;
4546 default: 4495 default:
4547 UNREACHABLE(); 4496 UNREACHABLE();
4548 } 4497 }
4549 } 4498 }
4550 4499
4551 4500
4552 Vector<const int> CharacterRange::GetWordBounds() { 4501 void CharacterRange::AddCaseEquivalents(
4553 return Vector<const int>(kWordRanges, kWordRangeCount - 1); 4502 ZoneGrowableArray<CharacterRange>* ranges,
4554 } 4503 bool is_one_byte,
4504 Isolate* isolate) {
4505 uint16_t bottom = from();
4506 uint16_t top = to();
4507 if (is_one_byte && !RangeContainsLatin1Equivalents(*this)) {
4508 if (bottom > Symbols::kMaxOneCharCodeSymbol) return;
4509 if (top > Symbols::kMaxOneCharCodeSymbol) {
4510 top = Symbols::kMaxOneCharCodeSymbol;
4511 }
4512 }
4555 4513
4556 4514 unibrow::Mapping<unibrow::Ecma262UnCanonicalize> jsregexp_uncanonicalize;
4557 class CharacterRangeSplitter { 4515 unibrow::Mapping<unibrow::CanonicalizationRange> jsregexp_canonrange;
4558 public: 4516 int32_t chars[unibrow::Ecma262UnCanonicalize::kMaxWidth];
4559 CharacterRangeSplitter(ZoneList<CharacterRange>** included,
4560 ZoneList<CharacterRange>** excluded,
4561 Zone* zone)
4562 : included_(included),
4563 excluded_(excluded),
4564 zone_(zone) { }
4565 void Call(uc16 from, DispatchTable::Entry entry);
4566
4567 static const int kInBase = 0;
4568 static const int kInOverlay = 1;
4569
4570 private:
4571 ZoneList<CharacterRange>** included_;
4572 ZoneList<CharacterRange>** excluded_;
4573 Zone* zone_;
4574 };
4575
4576
4577 void CharacterRangeSplitter::Call(uc16 from, DispatchTable::Entry entry) {
4578 if (!entry.out_set()->Get(kInBase)) return;
4579 ZoneList<CharacterRange>** target = entry.out_set()->Get(kInOverlay)
4580 ? included_
4581 : excluded_;
4582 if (*target == NULL) *target = new(zone_) ZoneList<CharacterRange>(2, zone_);
4583 (*target)->Add(CharacterRange(entry.from(), entry.to()), zone_);
4584 }
4585
4586
4587 void CharacterRange::Split(ZoneList<CharacterRange>* base,
4588 Vector<const int> overlay,
4589 ZoneList<CharacterRange>** included,
4590 ZoneList<CharacterRange>** excluded,
4591 Zone* zone) {
4592 DCHECK_EQ(NULL, *included);
4593 DCHECK_EQ(NULL, *excluded);
4594 DispatchTable table(zone);
4595 for (int i = 0; i < base->length(); i++)
4596 table.AddRange(base->at(i), CharacterRangeSplitter::kInBase, zone);
4597 for (int i = 0; i < overlay.length(); i += 2) {
4598 table.AddRange(CharacterRange(overlay[i], overlay[i + 1] - 1),
4599 CharacterRangeSplitter::kInOverlay, zone);
4600 }
4601 CharacterRangeSplitter callback(included, excluded, zone);
4602 table.ForEach(&callback);
4603 }
4604
4605
4606 void CharacterRange::AddCaseEquivalents(ZoneList<CharacterRange>* ranges,
4607 bool is_one_byte, Zone* zone) {
4608 Isolate* isolate = zone->isolate();
4609 uc16 bottom = from();
4610 uc16 top = to();
4611 if (is_one_byte && !RangeContainsLatin1Equivalents(*this)) {
4612 if (bottom > String::kMaxOneByteCharCode) return;
4613 if (top > String::kMaxOneByteCharCode) top = String::kMaxOneByteCharCode;
4614 }
4615 unibrow::uchar chars[unibrow::Ecma262UnCanonicalize::kMaxWidth];
4616 if (top == bottom) { 4517 if (top == bottom) {
4617 // If this is a singleton we just expand the one character. 4518 // If this is a singleton we just expand the one character.
4618 int length = isolate->jsregexp_uncanonicalize()->get(bottom, '\0', chars); 4519 intptr_t length = jsregexp_uncanonicalize.get(bottom, '\0', chars); // NOLIN T
4619 for (int i = 0; i < length; i++) { 4520 for (intptr_t i = 0; i < length; i++) {
4620 uc32 chr = chars[i]; 4521 uint32_t chr = chars[i];
4621 if (chr != bottom) { 4522 if (chr != bottom) {
4622 ranges->Add(CharacterRange::Singleton(chars[i]), zone); 4523 ranges->Add(CharacterRange::Singleton(chars[i]));
4623 } 4524 }
4624 } 4525 }
4625 } else { 4526 } else {
4626 // If this is a range we expand the characters block by block, 4527 // If this is a range we expand the characters block by block,
4627 // expanding contiguous subranges (blocks) one at a time. 4528 // expanding contiguous subranges (blocks) one at a time.
4628 // The approach is as follows. For a given start character we 4529 // The approach is as follows. For a given start character we
4629 // look up the remainder of the block that contains it (represented 4530 // look up the remainder of the block that contains it (represented
4630 // by the end point), for instance we find 'z' if the character 4531 // by the end point), for instance we find 'z' if the character
4631 // is 'c'. A block is characterized by the property 4532 // is 'c'. A block is characterized by the property
4632 // that all characters uncanonicalize in the same way, except that 4533 // that all characters uncanonicalize in the same way, except that
4633 // each entry in the result is incremented by the distance from the first 4534 // each entry in the result is incremented by the distance from the first
4634 // element. So a-z is a block because 'a' uncanonicalizes to ['a', 'A'] and 4535 // element. So a-z is a block because 'a' uncanonicalizes to ['a', 'A'] and
4635 // the k'th letter uncanonicalizes to ['a' + k, 'A' + k]. 4536 // the k'th letter uncanonicalizes to ['a' + k, 'A' + k].
4636 // Once we've found the end point we look up its uncanonicalization 4537 // Once we've found the end point we look up its uncanonicalization
4637 // and produce a range for each element. For instance for [c-f] 4538 // and produce a range for each element. For instance for [c-f]
4638 // we look up ['z', 'Z'] and produce [c-f] and [C-F]. We then only 4539 // we look up ['z', 'Z'] and produce [c-f] and [C-F]. We then only
4639 // add a range if it is not already contained in the input, so [c-f] 4540 // add a range if it is not already contained in the input, so [c-f]
4640 // will be skipped but [C-F] will be added. If this range is not 4541 // will be skipped but [C-F] will be added. If this range is not
4641 // completely contained in a block we do this for all the blocks 4542 // completely contained in a block we do this for all the blocks
4642 // covered by the range (handling characters that is not in a block 4543 // covered by the range (handling characters that is not in a block
4643 // as a "singleton block"). 4544 // as a "singleton block").
4644 unibrow::uchar range[unibrow::Ecma262UnCanonicalize::kMaxWidth]; 4545 int32_t range[unibrow::Ecma262UnCanonicalize::kMaxWidth];
4645 int pos = bottom; 4546 intptr_t pos = bottom;
4646 while (pos <= top) { 4547 while (pos <= top) {
4647 int length = isolate->jsregexp_canonrange()->get(pos, '\0', range); 4548 intptr_t length = jsregexp_canonrange.get(pos, '\0', range);
4648 uc16 block_end; 4549 uint16_t block_end;
4649 if (length == 0) { 4550 if (length == 0) {
4650 block_end = pos; 4551 block_end = pos;
4651 } else { 4552 } else {
4652 DCHECK_EQ(1, length); 4553 ASSERT(length == 1);
4653 block_end = range[0]; 4554 block_end = range[0];
4654 } 4555 }
4655 int end = (block_end > top) ? top : block_end; 4556 intptr_t end = (block_end > top) ? top : block_end;
4656 length = isolate->jsregexp_uncanonicalize()->get(block_end, '\0', range); 4557 length = jsregexp_uncanonicalize.get(block_end, '\0', range); // NOLINT
4657 for (int i = 0; i < length; i++) { 4558 for (intptr_t i = 0; i < length; i++) {
4658 uc32 c = range[i]; 4559 uint32_t c = range[i];
4659 uc16 range_from = c - (block_end - pos); 4560 uint16_t range_from = c - (block_end - pos);
4660 uc16 range_to = c - (block_end - end); 4561 uint16_t range_to = c - (block_end - end);
4661 if (!(bottom <= range_from && range_to <= top)) { 4562 if (!(bottom <= range_from && range_to <= top)) {
4662 ranges->Add(CharacterRange(range_from, range_to), zone); 4563 ranges->Add(CharacterRange(range_from, range_to));
4663 } 4564 }
4664 } 4565 }
4665 pos = end + 1; 4566 pos = end + 1;
4666 } 4567 }
4667 } 4568 }
4668 } 4569 }
4669 4570
4670 4571
4671 bool CharacterRange::IsCanonical(ZoneList<CharacterRange>* ranges) { 4572 bool CharacterRange::IsCanonical(ZoneGrowableArray<CharacterRange>* ranges) {
4672 DCHECK_NOT_NULL(ranges); 4573 ASSERT(ranges != NULL);
4673 int n = ranges->length(); 4574 intptr_t n = ranges->length();
4674 if (n <= 1) return true; 4575 if (n <= 1) return true;
4675 int max = ranges->at(0).to(); 4576 intptr_t max = ranges->At(0).to();
4676 for (int i = 1; i < n; i++) { 4577 for (intptr_t i = 1; i < n; i++) {
4677 CharacterRange next_range = ranges->at(i); 4578 CharacterRange next_range = ranges->At(i);
4678 if (next_range.from() <= max + 1) return false; 4579 if (next_range.from() <= max + 1) return false;
4679 max = next_range.to(); 4580 max = next_range.to();
4680 } 4581 }
4681 return true; 4582 return true;
4682 } 4583 }
4683 4584
4684 4585
4685 ZoneList<CharacterRange>* CharacterSet::ranges(Zone* zone) { 4586 ZoneGrowableArray<CharacterRange>* CharacterSet::ranges() {
4686 if (ranges_ == NULL) { 4587 if (ranges_ == NULL) {
4687 ranges_ = new(zone) ZoneList<CharacterRange>(2, zone); 4588 ranges_ = new ZoneGrowableArray<CharacterRange>(2);
4688 CharacterRange::AddClassEscape(standard_set_type_, ranges_, zone); 4589 CharacterRange::AddClassEscape(standard_set_type_, ranges_);
4689 } 4590 }
4690 return ranges_; 4591 return ranges_;
4691 } 4592 }
4692 4593
4693 4594
4694 // Move a number of elements in a zonelist to another position 4595 // Move a number of elements in a zone array to another position
4695 // in the same list. Handles overlapping source and target areas. 4596 // in the same array. Handles overlapping source and target areas.
4696 static void MoveRanges(ZoneList<CharacterRange>* list, 4597 static void MoveRanges(ZoneGrowableArray<CharacterRange>* list,
4697 int from, 4598 intptr_t from,
4698 int to, 4599 intptr_t to,
4699 int count) { 4600 intptr_t count) {
4700 // Ranges are potentially overlapping. 4601 // Ranges are potentially overlapping.
4701 if (from < to) { 4602 if (from < to) {
4702 for (int i = count - 1; i >= 0; i--) { 4603 for (intptr_t i = count - 1; i >= 0; i--) {
4703 list->at(to + i) = list->at(from + i); 4604 (*list)[to + i] = list->At(from + i);
4704 } 4605 }
4705 } else { 4606 } else {
4706 for (int i = 0; i < count; i++) { 4607 for (intptr_t i = 0; i < count; i++) {
4707 list->at(to + i) = list->at(from + i); 4608 (*list)[to + i] = list->At(from + i);
4708 } 4609 }
4709 } 4610 }
4710 } 4611 }
4711 4612
4712 4613
4713 static int InsertRangeInCanonicalList(ZoneList<CharacterRange>* list, 4614 static intptr_t InsertRangeInCanonicalList(
4714 int count, 4615 ZoneGrowableArray<CharacterRange>* list,
4715 CharacterRange insert) { 4616 intptr_t count,
4617 CharacterRange insert) {
4716 // Inserts a range into list[0..count[, which must be sorted 4618 // Inserts a range into list[0..count[, which must be sorted
4717 // by from value and non-overlapping and non-adjacent, using at most 4619 // by from value and non-overlapping and non-adjacent, using at most
4718 // list[0..count] for the result. Returns the number of resulting 4620 // list[0..count] for the result. Returns the number of resulting
4719 // canonicalized ranges. Inserting a range may collapse existing ranges into 4621 // canonicalized ranges. Inserting a range may collapse existing ranges into
4720 // fewer ranges, so the return value can be anything in the range 1..count+1. 4622 // fewer ranges, so the return value can be anything in the range 1..count+1.
4721 uc16 from = insert.from(); 4623 uint16_t from = insert.from();
4722 uc16 to = insert.to(); 4624 uint16_t to = insert.to();
4723 int start_pos = 0; 4625 intptr_t start_pos = 0;
4724 int end_pos = count; 4626 intptr_t end_pos = count;
4725 for (int i = count - 1; i >= 0; i--) { 4627 for (intptr_t i = count - 1; i >= 0; i--) {
4726 CharacterRange current = list->at(i); 4628 CharacterRange current = list->At(i);
4727 if (current.from() > to + 1) { 4629 if (current.from() > to + 1) {
4728 end_pos = i; 4630 end_pos = i;
4729 } else if (current.to() + 1 < from) { 4631 } else if (current.to() + 1 < from) {
4730 start_pos = i + 1; 4632 start_pos = i + 1;
4731 break; 4633 break;
4732 } 4634 }
4733 } 4635 }
4734 4636
4735 // Inserted range overlaps, or is adjacent to, ranges at positions 4637 // Inserted range overlaps, or is adjacent to, ranges at positions
4736 // [start_pos..end_pos[. Ranges before start_pos or at or after end_pos are 4638 // [start_pos..end_pos[. Ranges before start_pos or at or after end_pos are
4737 // not affected by the insertion. 4639 // not affected by the insertion.
4738 // If start_pos == end_pos, the range must be inserted before start_pos. 4640 // If start_pos == end_pos, the range must be inserted before start_pos.
4739 // if start_pos < end_pos, the entire range from start_pos to end_pos 4641 // if start_pos < end_pos, the entire range from start_pos to end_pos
4740 // must be merged with the insert range. 4642 // must be merged with the insert range.
4741 4643
4742 if (start_pos == end_pos) { 4644 if (start_pos == end_pos) {
4743 // Insert between existing ranges at position start_pos. 4645 // Insert between existing ranges at position start_pos.
4744 if (start_pos < count) { 4646 if (start_pos < count) {
4745 MoveRanges(list, start_pos, start_pos + 1, count - start_pos); 4647 MoveRanges(list, start_pos, start_pos + 1, count - start_pos);
4746 } 4648 }
4747 list->at(start_pos) = insert; 4649 (*list)[start_pos] = insert;
4748 return count + 1; 4650 return count + 1;
4749 } 4651 }
4750 if (start_pos + 1 == end_pos) { 4652 if (start_pos + 1 == end_pos) {
4751 // Replace single existing range at position start_pos. 4653 // Replace single existing range at position start_pos.
4752 CharacterRange to_replace = list->at(start_pos); 4654 CharacterRange to_replace = list->At(start_pos);
4753 int new_from = Min(to_replace.from(), from); 4655 intptr_t new_from = Utils::Minimum(to_replace.from(), from);
4754 int new_to = Max(to_replace.to(), to); 4656 intptr_t new_to = Utils::Maximum(to_replace.to(), to);
4755 list->at(start_pos) = CharacterRange(new_from, new_to); 4657 (*list)[start_pos] = CharacterRange(new_from, new_to);
4756 return count; 4658 return count;
4757 } 4659 }
4758 // Replace a number of existing ranges from start_pos to end_pos - 1. 4660 // Replace a number of existing ranges from start_pos to end_pos - 1.
4759 // Move the remaining ranges down. 4661 // Move the remaining ranges down.
4760 4662
4761 int new_from = Min(list->at(start_pos).from(), from); 4663 intptr_t new_from = Utils::Minimum(list->At(start_pos).from(), from);
4762 int new_to = Max(list->at(end_pos - 1).to(), to); 4664 intptr_t new_to = Utils::Maximum(list->At(end_pos - 1).to(), to);
4763 if (end_pos < count) { 4665 if (end_pos < count) {
4764 MoveRanges(list, end_pos, start_pos + 1, count - end_pos); 4666 MoveRanges(list, end_pos, start_pos + 1, count - end_pos);
4765 } 4667 }
4766 list->at(start_pos) = CharacterRange(new_from, new_to); 4668 (*list)[start_pos] = CharacterRange(new_from, new_to);
4767 return count - (end_pos - start_pos) + 1; 4669 return count - (end_pos - start_pos) + 1;
4768 } 4670 }
4769 4671
4770 4672
4771 void CharacterSet::Canonicalize() { 4673 void CharacterSet::Canonicalize() {
4772 // Special/default classes are always considered canonical. The result 4674 // Special/default classes are always considered canonical. The result
4773 // of calling ranges() will be sorted. 4675 // of calling ranges() will be sorted.
4774 if (ranges_ == NULL) return; 4676 if (ranges_ == NULL) return;
4775 CharacterRange::Canonicalize(ranges_); 4677 CharacterRange::Canonicalize(ranges_);
4776 } 4678 }
4777 4679
4778 4680
4779 void CharacterRange::Canonicalize(ZoneList<CharacterRange>* character_ranges) { 4681 void CharacterRange::Canonicalize(
4682 ZoneGrowableArray<CharacterRange>* character_ranges) {
4780 if (character_ranges->length() <= 1) return; 4683 if (character_ranges->length() <= 1) return;
4781 // Check whether ranges are already canonical (increasing, non-overlapping, 4684 // Check whether ranges are already canonical (increasing, non-overlapping,
4782 // non-adjacent). 4685 // non-adjacent).
4783 int n = character_ranges->length(); 4686 intptr_t n = character_ranges->length();
4784 int max = character_ranges->at(0).to(); 4687 intptr_t max = character_ranges->At(0).to();
4785 int i = 1; 4688 intptr_t i = 1;
4786 while (i < n) { 4689 while (i < n) {
4787 CharacterRange current = character_ranges->at(i); 4690 CharacterRange current = character_ranges->At(i);
4788 if (current.from() <= max + 1) { 4691 if (current.from() <= max + 1) {
4789 break; 4692 break;
4790 } 4693 }
4791 max = current.to(); 4694 max = current.to();
4792 i++; 4695 i++;
4793 } 4696 }
4794 // Canonical until the i'th range. If that's all of them, we are done. 4697 // Canonical until the i'th range. If that's all of them, we are done.
4795 if (i == n) return; 4698 if (i == n) return;
4796 4699
4797 // The ranges at index i and forward are not canonicalized. Make them so by 4700 // The ranges at index i and forward are not canonicalized. Make them so by
4798 // doing the equivalent of insertion sort (inserting each into the previous 4701 // doing the equivalent of insertion sort (inserting each into the previous
4799 // list, in order). 4702 // list, in order).
4800 // Notice that inserting a range can reduce the number of ranges in the 4703 // Notice that inserting a range can reduce the number of ranges in the
4801 // result due to combining of adjacent and overlapping ranges. 4704 // result due to combining of adjacent and overlapping ranges.
4802 int read = i; // Range to insert. 4705 intptr_t read = i; // Range to insert.
4803 int num_canonical = i; // Length of canonicalized part of list. 4706 intptr_t num_canonical = i; // Length of canonicalized part of list.
4804 do { 4707 do {
4805 num_canonical = InsertRangeInCanonicalList(character_ranges, 4708 num_canonical = InsertRangeInCanonicalList(character_ranges,
4806 num_canonical, 4709 num_canonical,
4807 character_ranges->at(read)); 4710 character_ranges->At(read));
4808 read++; 4711 read++;
4809 } while (read < n); 4712 } while (read < n);
4810 character_ranges->Rewind(num_canonical); 4713 character_ranges->TruncateTo(num_canonical);
4811 4714
4812 DCHECK(CharacterRange::IsCanonical(character_ranges)); 4715 ASSERT(CharacterRange::IsCanonical(character_ranges));
4813 } 4716 }
4814 4717
4815 4718
4816 void CharacterRange::Negate(ZoneList<CharacterRange>* ranges, 4719 void CharacterRange::Negate(ZoneGrowableArray<CharacterRange>* ranges,
4817 ZoneList<CharacterRange>* negated_ranges, 4720 ZoneGrowableArray<CharacterRange>* negated_ranges) {
4818 Zone* zone) { 4721 ASSERT(CharacterRange::IsCanonical(ranges));
4819 DCHECK(CharacterRange::IsCanonical(ranges)); 4722 ASSERT(negated_ranges->length() == 0);
4820 DCHECK_EQ(0, negated_ranges->length()); 4723 intptr_t range_count = ranges->length();
4821 int range_count = ranges->length(); 4724 uint16_t from = 0;
4822 uc16 from = 0; 4725 intptr_t i = 0;
4823 int i = 0; 4726 if (range_count > 0 && ranges->At(0).from() == 0) {
4824 if (range_count > 0 && ranges->at(0).from() == 0) { 4727 from = ranges->At(0).to();
4825 from = ranges->at(0).to();
4826 i = 1; 4728 i = 1;
4827 } 4729 }
4828 while (i < range_count) { 4730 while (i < range_count) {
4829 CharacterRange range = ranges->at(i); 4731 CharacterRange range = ranges->At(i);
4830 negated_ranges->Add(CharacterRange(from + 1, range.from() - 1), zone); 4732 negated_ranges->Add(CharacterRange(from + 1, range.from() - 1));
4831 from = range.to(); 4733 from = range.to();
4832 i++; 4734 i++;
4833 } 4735 }
4834 if (from < String::kMaxUtf16CodeUnit) { 4736 if (from < Utf16::kMaxCodeUnit) {
4835 negated_ranges->Add(CharacterRange(from + 1, String::kMaxUtf16CodeUnit), 4737 negated_ranges->Add(CharacterRange(from + 1, Utf16::kMaxCodeUnit));
4836 zone);
4837 } 4738 }
4838 } 4739 }
4839 4740
4840 4741
4841 // ------------------------------------------------------------------- 4742 // -------------------------------------------------------------------
4842 // Splay tree 4743 // Splay tree
4843 4744
4844 4745
4845 OutSet* OutSet::Extend(unsigned value, Zone* zone) { 4746 // Workaround for the fact that ZoneGrowableArray does not have contains().
4846 if (Get(value)) 4747 static bool ArrayContains(ZoneGrowableArray<unsigned>* array,
4847 return this; 4748 unsigned value) {
4848 if (successors(zone) != NULL) { 4749 for (intptr_t i = 0; i < array->length(); i++) {
4849 for (int i = 0; i < successors(zone)->length(); i++) { 4750 if (array->At(i) == value) {
4850 OutSet* successor = successors(zone)->at(i); 4751 return true;
4851 if (successor->Get(value))
4852 return successor;
4853 } 4752 }
4854 } else {
4855 successors_ = new(zone) ZoneList<OutSet*>(2, zone);
4856 } 4753 }
4857 OutSet* result = new(zone) OutSet(first_, remaining_); 4754 return false;
4858 result->Set(value, zone);
4859 successors(zone)->Add(result, zone);
4860 return result;
4861 } 4755 }
4862 4756
4863 4757
4864 void OutSet::Set(unsigned value, Zone *zone) { 4758 void OutSet::Set(unsigned value, Isolate* isolate) {
4865 if (value < kFirstLimit) { 4759 if (value < kFirstLimit) {
4866 first_ |= (1 << value); 4760 first_ |= (1 << value);
4867 } else { 4761 } else {
4868 if (remaining_ == NULL) 4762 if (remaining_ == NULL)
4869 remaining_ = new(zone) ZoneList<unsigned>(1, zone); 4763 remaining_ = new(isolate) ZoneGrowableArray<unsigned>(1);
4870 if (remaining_->is_empty() || !remaining_->Contains(value)) 4764
4871 remaining_->Add(value, zone); 4765 bool remaining_contains_value = ArrayContains(remaining_, value);
4766 if (remaining_->is_empty() || !remaining_contains_value) {
4767 remaining_->Add(value);
4768 }
4872 } 4769 }
4873 } 4770 }
4874 4771
4875 4772
4876 bool OutSet::Get(unsigned value) const { 4773 bool OutSet::Get(unsigned value) const {
4877 if (value < kFirstLimit) { 4774 if (value < kFirstLimit) {
4878 return (first_ & (1 << value)) != 0; 4775 return (first_ & (1 << value)) != 0;
4879 } else if (remaining_ == NULL) { 4776 } else if (remaining_ == NULL) {
4880 return false; 4777 return false;
4881 } else { 4778 } else {
4882 return remaining_->Contains(value); 4779 return ArrayContains(remaining_, value);
4883 } 4780 }
4884 } 4781 }
4885 4782
4886 4783
4887 const uc16 DispatchTable::Config::kNoKey = unibrow::Utf8::kBadChar;
4888
4889
4890 void DispatchTable::AddRange(CharacterRange full_range, int value,
4891 Zone* zone) {
4892 CharacterRange current = full_range;
4893 if (tree()->is_empty()) {
4894 // If this is the first range we just insert into the table.
4895 ZoneSplayTree<Config>::Locator loc;
4896 DCHECK_RESULT(tree()->Insert(current.from(), &loc));
4897 loc.set_value(Entry(current.from(), current.to(),
4898 empty()->Extend(value, zone)));
4899 return;
4900 }
4901 // First see if there is a range to the left of this one that
4902 // overlaps.
4903 ZoneSplayTree<Config>::Locator loc;
4904 if (tree()->FindGreatestLessThan(current.from(), &loc)) {
4905 Entry* entry = &loc.value();
4906 // If we've found a range that overlaps with this one, and it
4907 // starts strictly to the left of this one, we have to fix it
4908 // because the following code only handles ranges that start on
4909 // or after the start point of the range we're adding.
4910 if (entry->from() < current.from() && entry->to() >= current.from()) {
4911 // Snap the overlapping range in half around the start point of
4912 // the range we're adding.
4913 CharacterRange left(entry->from(), current.from() - 1);
4914 CharacterRange right(current.from(), entry->to());
4915 // The left part of the overlapping range doesn't overlap.
4916 // Truncate the whole entry to be just the left part.
4917 entry->set_to(left.to());
4918 // The right part is the one that overlaps. We add this part
4919 // to the map and let the next step deal with merging it with
4920 // the range we're adding.
4921 ZoneSplayTree<Config>::Locator loc;
4922 DCHECK_RESULT(tree()->Insert(right.from(), &loc));
4923 loc.set_value(Entry(right.from(),
4924 right.to(),
4925 entry->out_set()));
4926 }
4927 }
4928 while (current.is_valid()) {
4929 if (tree()->FindLeastGreaterThan(current.from(), &loc) &&
4930 (loc.value().from() <= current.to()) &&
4931 (loc.value().to() >= current.from())) {
4932 Entry* entry = &loc.value();
4933 // We have overlap. If there is space between the start point of
4934 // the range we're adding and where the overlapping range starts
4935 // then we have to add a range covering just that space.
4936 if (current.from() < entry->from()) {
4937 ZoneSplayTree<Config>::Locator ins;
4938 DCHECK_RESULT(tree()->Insert(current.from(), &ins));
4939 ins.set_value(Entry(current.from(),
4940 entry->from() - 1,
4941 empty()->Extend(value, zone)));
4942 current.set_from(entry->from());
4943 }
4944 DCHECK_EQ(current.from(), entry->from());
4945 // If the overlapping range extends beyond the one we want to add
4946 // we have to snap the right part off and add it separately.
4947 if (entry->to() > current.to()) {
4948 ZoneSplayTree<Config>::Locator ins;
4949 DCHECK_RESULT(tree()->Insert(current.to() + 1, &ins));
4950 ins.set_value(Entry(current.to() + 1,
4951 entry->to(),
4952 entry->out_set()));
4953 entry->set_to(current.to());
4954 }
4955 DCHECK(entry->to() <= current.to());
4956 // The overlapping range is now completely contained by the range
4957 // we're adding so we can just update it and move the start point
4958 // of the range we're adding just past it.
4959 entry->AddValue(value, zone);
4960 // Bail out if the last interval ended at 0xFFFF since otherwise
4961 // adding 1 will wrap around to 0.
4962 if (entry->to() == String::kMaxUtf16CodeUnit)
4963 break;
4964 DCHECK(entry->to() + 1 > current.from());
4965 current.set_from(entry->to() + 1);
4966 } else {
4967 // There is no overlap so we can just add the range
4968 ZoneSplayTree<Config>::Locator ins;
4969 DCHECK_RESULT(tree()->Insert(current.from(), &ins));
4970 ins.set_value(Entry(current.from(),
4971 current.to(),
4972 empty()->Extend(value, zone)));
4973 break;
4974 }
4975 }
4976 }
4977
4978
4979 OutSet* DispatchTable::Get(uc16 value) {
4980 ZoneSplayTree<Config>::Locator loc;
4981 if (!tree()->FindGreatestLessThan(value, &loc))
4982 return empty();
4983 Entry* entry = &loc.value();
4984 if (value <= entry->to())
4985 return entry->out_set();
4986 else
4987 return empty();
4988 }
4989
4990
4991 // ------------------------------------------------------------------- 4784 // -------------------------------------------------------------------
4992 // Analysis 4785 // Analysis
4993 4786
4994 4787
4995 void Analysis::EnsureAnalyzed(RegExpNode* that) { 4788 void Analysis::EnsureAnalyzed(RegExpNode* that) {
4996 StackLimitCheck check(that->zone()->isolate());
4997 if (check.HasOverflowed()) {
4998 fail("Stack overflow");
4999 return;
5000 }
5001 if (that->info()->been_analyzed || that->info()->being_analyzed) 4789 if (that->info()->been_analyzed || that->info()->being_analyzed)
5002 return; 4790 return;
5003 that->info()->being_analyzed = true; 4791 that->info()->being_analyzed = true;
5004 that->Accept(this); 4792 that->Accept(this);
5005 that->info()->being_analyzed = false; 4793 that->info()->being_analyzed = false;
5006 that->info()->been_analyzed = true; 4794 that->info()->been_analyzed = true;
5007 } 4795 }
5008 4796
5009 4797
5010 void Analysis::VisitEnd(EndNode* that) { 4798 void Analysis::VisitEnd(EndNode* that) {
5011 // nothing to do 4799 // nothing to do
5012 } 4800 }
5013 4801
5014 4802
5015 void TextNode::CalculateOffsets() { 4803 void TextNode::CalculateOffsets() {
5016 int element_count = elements()->length(); 4804 intptr_t element_count = elements()->length();
5017 // Set up the offsets of the elements relative to the start. This is a fixed 4805 // Set up the offsets of the elements relative to the start. This is a fixed
5018 // quantity since a TextNode can only contain fixed-width things. 4806 // quantity since a TextNode can only contain fixed-width things.
5019 int cp_offset = 0; 4807 intptr_t cp_offset = 0;
5020 for (int i = 0; i < element_count; i++) { 4808 for (intptr_t i = 0; i < element_count; i++) {
5021 TextElement& elm = elements()->at(i); 4809 TextElement& elm = (*elements())[i];
5022 elm.set_cp_offset(cp_offset); 4810 elm.set_cp_offset(cp_offset);
5023 cp_offset += elm.length(); 4811 cp_offset += elm.length();
5024 } 4812 }
5025 } 4813 }
5026 4814
5027 4815
5028 void Analysis::VisitText(TextNode* that) { 4816 void Analysis::VisitText(TextNode* that) {
5029 if (ignore_case_) { 4817 if (ignore_case_) {
5030 that->MakeCaseIndependent(is_one_byte_); 4818 that->MakeCaseIndependent(is_one_byte_);
5031 } 4819 }
(...skipping 10 matching lines...) Expand all
5042 if (!has_failed()) { 4830 if (!has_failed()) {
5043 // If the next node is interested in what it follows then this node 4831 // If the next node is interested in what it follows then this node
5044 // has to be interested too so it can pass the information on. 4832 // has to be interested too so it can pass the information on.
5045 that->info()->AddFromFollowing(target->info()); 4833 that->info()->AddFromFollowing(target->info());
5046 } 4834 }
5047 } 4835 }
5048 4836
5049 4837
5050 void Analysis::VisitChoice(ChoiceNode* that) { 4838 void Analysis::VisitChoice(ChoiceNode* that) {
5051 NodeInfo* info = that->info(); 4839 NodeInfo* info = that->info();
5052 for (int i = 0; i < that->alternatives()->length(); i++) { 4840 for (intptr_t i = 0; i < that->alternatives()->length(); i++) {
5053 RegExpNode* node = that->alternatives()->at(i).node(); 4841 RegExpNode* node = (*that->alternatives())[i].node();
5054 EnsureAnalyzed(node); 4842 EnsureAnalyzed(node);
5055 if (has_failed()) return; 4843 if (has_failed()) return;
5056 // Anything the following nodes need to know has to be known by 4844 // Anything the following nodes need to know has to be known by
5057 // this node also, so it can pass it on. 4845 // this node also, so it can pass it on.
5058 info->AddFromFollowing(node->info()); 4846 info->AddFromFollowing(node->info());
5059 } 4847 }
5060 } 4848 }
5061 4849
5062 4850
5063 void Analysis::VisitLoopChoice(LoopChoiceNode* that) { 4851 void Analysis::VisitLoopChoice(LoopChoiceNode* that) {
5064 NodeInfo* info = that->info(); 4852 NodeInfo* info = that->info();
5065 for (int i = 0; i < that->alternatives()->length(); i++) { 4853 for (intptr_t i = 0; i < that->alternatives()->length(); i++) {
5066 RegExpNode* node = that->alternatives()->at(i).node(); 4854 RegExpNode* node = (*that->alternatives())[i].node();
5067 if (node != that->loop_node()) { 4855 if (node != that->loop_node()) {
5068 EnsureAnalyzed(node); 4856 EnsureAnalyzed(node);
5069 if (has_failed()) return; 4857 if (has_failed()) return;
5070 info->AddFromFollowing(node->info()); 4858 info->AddFromFollowing(node->info());
5071 } 4859 }
5072 } 4860 }
5073 // Check the loop last since it may need the value of this node 4861 // Check the loop last since it may need the value of this node
5074 // to get a correct result. 4862 // to get a correct result.
5075 EnsureAnalyzed(that->loop_node()); 4863 EnsureAnalyzed(that->loop_node());
5076 if (!has_failed()) { 4864 if (!has_failed()) {
5077 info->AddFromFollowing(that->loop_node()->info()); 4865 info->AddFromFollowing(that->loop_node()->info());
5078 } 4866 }
5079 } 4867 }
5080 4868
5081 4869
5082 void Analysis::VisitBackReference(BackReferenceNode* that) { 4870 void Analysis::VisitBackReference(BackReferenceNode* that) {
5083 EnsureAnalyzed(that->on_success()); 4871 EnsureAnalyzed(that->on_success());
5084 } 4872 }
5085 4873
5086 4874
5087 void Analysis::VisitAssertion(AssertionNode* that) { 4875 void Analysis::VisitAssertion(AssertionNode* that) {
5088 EnsureAnalyzed(that->on_success()); 4876 EnsureAnalyzed(that->on_success());
5089 } 4877 }
5090 4878
5091 4879
5092 void BackReferenceNode::FillInBMInfo(int offset, 4880 void BackReferenceNode::FillInBMInfo(intptr_t offset,
5093 int budget, 4881 intptr_t budget,
5094 BoyerMooreLookahead* bm, 4882 BoyerMooreLookahead* bm,
5095 bool not_at_start) { 4883 bool not_at_start) {
5096 // Working out the set of characters that a backreference can match is too 4884 // Working out the set of characters that a backreference can match is too
5097 // hard, so we just say that any character can match. 4885 // hard, so we just say that any character can match.
5098 bm->SetRest(offset); 4886 bm->SetRest(offset);
5099 SaveBMInfo(bm, not_at_start, offset); 4887 SaveBMInfo(bm, not_at_start, offset);
5100 } 4888 }
5101 4889
5102 4890
5103 STATIC_ASSERT(BoyerMoorePositionInfo::kMapSize == 4891 COMPILE_ASSERT(BoyerMoorePositionInfo::kMapSize ==
5104 RegExpMacroAssembler::kTableSize); 4892 RegExpMacroAssembler::kTableSize);
5105 4893
5106 4894
5107 void ChoiceNode::FillInBMInfo(int offset, 4895 void ChoiceNode::FillInBMInfo(intptr_t offset,
5108 int budget, 4896 intptr_t budget,
5109 BoyerMooreLookahead* bm, 4897 BoyerMooreLookahead* bm,
5110 bool not_at_start) { 4898 bool not_at_start) {
5111 ZoneList<GuardedAlternative>* alts = alternatives(); 4899 ZoneGrowableArray<GuardedAlternative>* alts = alternatives();
5112 budget = (budget - 1) / alts->length(); 4900 budget = (budget - 1) / alts->length();
5113 for (int i = 0; i < alts->length(); i++) { 4901 for (intptr_t i = 0; i < alts->length(); i++) {
5114 GuardedAlternative& alt = alts->at(i); 4902 GuardedAlternative& alt = (*alts)[i];
5115 if (alt.guards() != NULL && alt.guards()->length() != 0) { 4903 if (alt.guards() != NULL && alt.guards()->length() != 0) {
5116 bm->SetRest(offset); // Give up trying to fill in info. 4904 bm->SetRest(offset); // Give up trying to fill in info.
5117 SaveBMInfo(bm, not_at_start, offset); 4905 SaveBMInfo(bm, not_at_start, offset);
5118 return; 4906 return;
5119 } 4907 }
5120 alt.node()->FillInBMInfo(offset, budget, bm, not_at_start); 4908 alt.node()->FillInBMInfo(offset, budget, bm, not_at_start);
5121 } 4909 }
5122 SaveBMInfo(bm, not_at_start, offset); 4910 SaveBMInfo(bm, not_at_start, offset);
5123 } 4911 }
5124 4912
5125 4913
5126 void TextNode::FillInBMInfo(int initial_offset, 4914 void TextNode::FillInBMInfo(intptr_t initial_offset,
5127 int budget, 4915 intptr_t budget,
5128 BoyerMooreLookahead* bm, 4916 BoyerMooreLookahead* bm,
5129 bool not_at_start) { 4917 bool not_at_start) {
5130 if (initial_offset >= bm->length()) return; 4918 if (initial_offset >= bm->length()) return;
5131 int offset = initial_offset; 4919 intptr_t offset = initial_offset;
5132 int max_char = bm->max_char(); 4920 intptr_t max_char = bm->max_char();
5133 for (int i = 0; i < elements()->length(); i++) { 4921 for (intptr_t i = 0; i < elements()->length(); i++) {
5134 if (offset >= bm->length()) { 4922 if (offset >= bm->length()) {
5135 if (initial_offset == 0) set_bm_info(not_at_start, bm); 4923 if (initial_offset == 0) set_bm_info(not_at_start, bm);
5136 return; 4924 return;
5137 } 4925 }
5138 TextElement text = elements()->at(i); 4926 TextElement text = elements()->At(i);
5139 if (text.text_type() == TextElement::ATOM) { 4927 if (text.text_type() == TextElement::ATOM) {
5140 RegExpAtom* atom = text.atom(); 4928 RegExpAtom* atom = text.atom();
5141 for (int j = 0; j < atom->length(); j++, offset++) { 4929 for (intptr_t j = 0; j < atom->length(); j++, offset++) {
5142 if (offset >= bm->length()) { 4930 if (offset >= bm->length()) {
5143 if (initial_offset == 0) set_bm_info(not_at_start, bm); 4931 if (initial_offset == 0) set_bm_info(not_at_start, bm);
5144 return; 4932 return;
5145 } 4933 }
5146 uc16 character = atom->data()[j]; 4934 uint16_t character = atom->data()->At(j);
5147 if (bm->compiler()->ignore_case()) { 4935 if (bm->compiler()->ignore_case()) {
5148 unibrow::uchar chars[unibrow::Ecma262UnCanonicalize::kMaxWidth]; 4936 int32_t chars[unibrow::Ecma262UnCanonicalize::kMaxWidth];
5149 int length = GetCaseIndependentLetters( 4937 intptr_t length = GetCaseIndependentLetters(
5150 Isolate::Current(),
5151 character, 4938 character,
5152 bm->max_char() == String::kMaxOneByteCharCode, 4939 bm->max_char() == Symbols::kMaxOneCharCodeSymbol,
5153 chars); 4940 chars);
5154 for (int j = 0; j < length; j++) { 4941 for (intptr_t j = 0; j < length; j++) {
5155 bm->Set(offset, chars[j]); 4942 bm->Set(offset, chars[j]);
5156 } 4943 }
5157 } else { 4944 } else {
5158 if (character <= max_char) bm->Set(offset, character); 4945 if (character <= max_char) bm->Set(offset, character);
5159 } 4946 }
5160 } 4947 }
5161 } else { 4948 } else {
5162 DCHECK_EQ(TextElement::CHAR_CLASS, text.text_type()); 4949 ASSERT(text.text_type() == TextElement::CHAR_CLASS);
5163 RegExpCharacterClass* char_class = text.char_class(); 4950 RegExpCharacterClass* char_class = text.char_class();
5164 ZoneList<CharacterRange>* ranges = char_class->ranges(zone()); 4951 ZoneGrowableArray<CharacterRange>* ranges = char_class->ranges();
5165 if (char_class->is_negated()) { 4952 if (char_class->is_negated()) {
5166 bm->SetAll(offset); 4953 bm->SetAll(offset);
5167 } else { 4954 } else {
5168 for (int k = 0; k < ranges->length(); k++) { 4955 for (intptr_t k = 0; k < ranges->length(); k++) {
5169 CharacterRange& range = ranges->at(k); 4956 CharacterRange& range = (*ranges)[k];
5170 if (range.from() > max_char) continue; 4957 if (range.from() > max_char) continue;
5171 int to = Min(max_char, static_cast<int>(range.to())); 4958 intptr_t to = Utils::Minimum(max_char,
4959 static_cast<intptr_t>(range.to()));
5172 bm->SetInterval(offset, Interval(range.from(), to)); 4960 bm->SetInterval(offset, Interval(range.from(), to));
5173 } 4961 }
5174 } 4962 }
5175 offset++; 4963 offset++;
5176 } 4964 }
5177 } 4965 }
5178 if (offset >= bm->length()) { 4966 if (offset >= bm->length()) {
5179 if (initial_offset == 0) set_bm_info(not_at_start, bm); 4967 if (initial_offset == 0) set_bm_info(not_at_start, bm);
5180 return; 4968 return;
5181 } 4969 }
5182 on_success()->FillInBMInfo(offset, 4970 on_success()->FillInBMInfo(offset,
5183 budget - 1, 4971 budget - 1,
5184 bm, 4972 bm,
5185 true); // Not at start after a text node. 4973 true); // Not at start after a text node.
5186 if (initial_offset == 0) set_bm_info(not_at_start, bm); 4974 if (initial_offset == 0) set_bm_info(not_at_start, bm);
5187 } 4975 }
5188 4976
5189 4977
5190 // -------------------------------------------------------------------
5191 // Dispatch table construction
5192
5193
5194 void DispatchTableConstructor::VisitEnd(EndNode* that) {
5195 AddRange(CharacterRange::Everything());
5196 }
5197
5198
5199 void DispatchTableConstructor::BuildTable(ChoiceNode* node) {
5200 node->set_being_calculated(true);
5201 ZoneList<GuardedAlternative>* alternatives = node->alternatives();
5202 for (int i = 0; i < alternatives->length(); i++) {
5203 set_choice_index(i);
5204 alternatives->at(i).node()->Accept(this);
5205 }
5206 node->set_being_calculated(false);
5207 }
5208
5209
5210 class AddDispatchRange {
5211 public:
5212 explicit AddDispatchRange(DispatchTableConstructor* constructor)
5213 : constructor_(constructor) { }
5214 void Call(uc32 from, DispatchTable::Entry entry);
5215 private:
5216 DispatchTableConstructor* constructor_;
5217 };
5218
5219
5220 void AddDispatchRange::Call(uc32 from, DispatchTable::Entry entry) {
5221 CharacterRange range(from, entry.to());
5222 constructor_->AddRange(range);
5223 }
5224
5225
5226 void DispatchTableConstructor::VisitChoice(ChoiceNode* node) {
5227 if (node->being_calculated())
5228 return;
5229 DispatchTable* table = node->GetTable(ignore_case_);
5230 AddDispatchRange adder(this);
5231 table->ForEach(&adder);
5232 }
5233
5234
5235 void DispatchTableConstructor::VisitBackReference(BackReferenceNode* that) {
5236 // TODO(160): Find the node that we refer back to and propagate its start
5237 // set back to here. For now we just accept anything.
5238 AddRange(CharacterRange::Everything());
5239 }
5240
5241
5242 void DispatchTableConstructor::VisitAssertion(AssertionNode* that) {
5243 RegExpNode* target = that->on_success();
5244 target->Accept(this);
5245 }
5246
5247
5248 static int CompareRangeByFrom(const CharacterRange* a,
5249 const CharacterRange* b) {
5250 return Compare<uc16>(a->from(), b->from());
5251 }
5252
5253
5254 void DispatchTableConstructor::AddInverse(ZoneList<CharacterRange>* ranges) {
5255 ranges->Sort(CompareRangeByFrom);
5256 uc16 last = 0;
5257 for (int i = 0; i < ranges->length(); i++) {
5258 CharacterRange range = ranges->at(i);
5259 if (last < range.from())
5260 AddRange(CharacterRange(last, range.from() - 1));
5261 if (range.to() >= last) {
5262 if (range.to() == String::kMaxUtf16CodeUnit) {
5263 return;
5264 } else {
5265 last = range.to() + 1;
5266 }
5267 }
5268 }
5269 AddRange(CharacterRange(last, String::kMaxUtf16CodeUnit));
5270 }
5271
5272
5273 void DispatchTableConstructor::VisitText(TextNode* that) {
5274 TextElement elm = that->elements()->at(0);
5275 switch (elm.text_type()) {
5276 case TextElement::ATOM: {
5277 uc16 c = elm.atom()->data()[0];
5278 AddRange(CharacterRange(c, c));
5279 break;
5280 }
5281 case TextElement::CHAR_CLASS: {
5282 RegExpCharacterClass* tree = elm.char_class();
5283 ZoneList<CharacterRange>* ranges = tree->ranges(that->zone());
5284 if (tree->is_negated()) {
5285 AddInverse(ranges);
5286 } else {
5287 for (int i = 0; i < ranges->length(); i++)
5288 AddRange(ranges->at(i));
5289 }
5290 break;
5291 }
5292 default: {
5293 UNIMPLEMENTED();
5294 }
5295 }
5296 }
5297
5298
5299 void DispatchTableConstructor::VisitAction(ActionNode* that) {
5300 RegExpNode* target = that->on_success();
5301 target->Accept(this);
5302 }
5303
5304
5305 RegExpEngine::CompilationResult RegExpEngine::Compile( 4978 RegExpEngine::CompilationResult RegExpEngine::Compile(
5306 RegExpCompileData* data, bool ignore_case, bool is_global, 4979 RegExpCompileData* data,
5307 bool is_multiline, bool is_sticky, Handle<String> pattern, 4980 const ParsedFunction* parsed_function,
5308 Handle<String> sample_subject, bool is_one_byte, Zone* zone) { 4981 const ZoneGrowableArray<const ICData*>& ic_data_array) {
5309 if ((data->capture_count + 1) * 2 - 1 > RegExpMacroAssembler::kMaxRegister) { 4982 Isolate* isolate = Isolate::Current();
5310 return IrregexpRegExpTooBig(zone->isolate());
5311 }
5312 RegExpCompiler compiler(data->capture_count, ignore_case, is_one_byte, zone);
5313 4983
5314 // Sample some characters from the middle of the string. 4984 const Function& function = parsed_function->function();
5315 static const int kSampleSize = 128; 4985 const intptr_t specialization_cid = function.regexp_cid();
4986 const bool is_one_byte = (specialization_cid == kOneByteStringCid ||
4987 specialization_cid == kExternalOneByteStringCid);
4988 JSRegExp& regexp = JSRegExp::Handle(isolate, function.regexp());
4989 const String& pattern = String::Handle(isolate, regexp.pattern());
5316 4990
5317 sample_subject = String::Flatten(sample_subject); 4991 ASSERT(!regexp.IsNull());
5318 int chars_sampled = 0; 4992 ASSERT(!pattern.IsNull());
5319 int half_way = (sample_subject->length() - kSampleSize) / 2; 4993
5320 for (int i = Max(0, half_way); 4994 const bool ignore_case = regexp.is_ignore_case();
5321 i < sample_subject->length() && chars_sampled < kSampleSize; 4995 const bool is_global = regexp.is_global();
5322 i++, chars_sampled++) { 4996
5323 compiler.frequency_collator()->CountCharacter(sample_subject->Get(i)); 4997 RegExpCompiler compiler(data->capture_count, ignore_case, specialization_cid);
5324 } 4998
4999 // TODO(zerny): Frequency sampling is currently disabled because of several
5000 // issues. We do not want to store subject strings in the regexp object since
5001 // they might be long and we should not prevent their garbage collection.
5002 // Passing them to this function explicitly does not help, since we must
5003 // generate exactly the same IR for both the unoptimizing and optimizing
5004 // pipelines (otherwise it gets confused when i.e. deopt id's differ).
5005 // An option would be to store sampling results in the regexp object, but
5006 // I'm not sure the performance gains are relevant enough.
5325 5007
5326 // Wrap the body of the regexp in capture #0. 5008 // Wrap the body of the regexp in capture #0.
5327 RegExpNode* captured_body = RegExpCapture::ToNode(data->tree, 5009 RegExpNode* captured_body = RegExpCapture::ToNode(data->tree,
5328 0, 5010 0,
5329 &compiler, 5011 &compiler,
5330 compiler.accept()); 5012 compiler.accept());
5013
5331 RegExpNode* node = captured_body; 5014 RegExpNode* node = captured_body;
5332 bool is_end_anchored = data->tree->IsAnchoredAtEnd(); 5015 bool is_end_anchored = data->tree->IsAnchoredAtEnd();
5333 bool is_start_anchored = data->tree->IsAnchoredAtStart(); 5016 bool is_start_anchored = data->tree->IsAnchoredAtStart();
5334 int max_length = data->tree->max_match(); 5017 intptr_t max_length = data->tree->max_match();
5335 if (!is_start_anchored && !is_sticky) { 5018 if (!is_start_anchored) {
5336 // Add a .*? at the beginning, outside the body capture, unless 5019 // Add a .*? at the beginning, outside the body capture, unless
5337 // this expression is anchored at the beginning or sticky. 5020 // this expression is anchored at the beginning.
5338 RegExpNode* loop_node = 5021 RegExpNode* loop_node =
5339 RegExpQuantifier::ToNode(0, 5022 RegExpQuantifier::ToNode(0,
5340 RegExpTree::kInfinity, 5023 RegExpTree::kInfinity,
5341 false, 5024 false,
5342 new(zone) RegExpCharacterClass('*'), 5025 new(isolate) RegExpCharacterClass('*'),
5343 &compiler, 5026 &compiler,
5344 captured_body, 5027 captured_body,
5345 data->contains_anchor); 5028 data->contains_anchor);
5346 5029
5347 if (data->contains_anchor) { 5030 if (data->contains_anchor) {
5348 // Unroll loop once, to take care of the case that might start 5031 // Unroll loop once, to take care of the case that might start
5349 // at the start of input. 5032 // at the start of input.
5350 ChoiceNode* first_step_node = new(zone) ChoiceNode(2, zone); 5033 ChoiceNode* first_step_node = new(isolate) ChoiceNode(2, isolate);
5351 first_step_node->AddAlternative(GuardedAlternative(captured_body)); 5034 first_step_node->AddAlternative(GuardedAlternative(captured_body));
5352 first_step_node->AddAlternative(GuardedAlternative( 5035 first_step_node->AddAlternative(GuardedAlternative(
5353 new(zone) TextNode(new(zone) RegExpCharacterClass('*'), loop_node))); 5036 new(isolate) TextNode(
5037 new(isolate) RegExpCharacterClass('*'), loop_node)));
5354 node = first_step_node; 5038 node = first_step_node;
5355 } else { 5039 } else {
5356 node = loop_node; 5040 node = loop_node;
5357 } 5041 }
5358 } 5042 }
5359 if (is_one_byte) { 5043 if (is_one_byte) {
5360 node = node->FilterOneByte(RegExpCompiler::kMaxRecursion, ignore_case); 5044 node = node->FilterOneByte(RegExpCompiler::kMaxRecursion, ignore_case);
5361 // Do it again to propagate the new nodes to places where they were not 5045 // Do it again to propagate the new nodes to places where they were not
5362 // put because they had not been calculated yet. 5046 // put because they had not been calculated yet.
5363 if (node != NULL) { 5047 if (node != NULL) {
5364 node = node->FilterOneByte(RegExpCompiler::kMaxRecursion, ignore_case); 5048 node = node->FilterOneByte(RegExpCompiler::kMaxRecursion, ignore_case);
5365 } 5049 }
5366 } 5050 }
5367 5051
5368 if (node == NULL) node = new(zone) EndNode(EndNode::BACKTRACK, zone); 5052 if (node == NULL) node = new(isolate) EndNode(EndNode::BACKTRACK, isolate);
5369 data->node = node; 5053 data->node = node;
5370 Analysis analysis(ignore_case, is_one_byte); 5054 Analysis analysis(ignore_case, is_one_byte);
5371 analysis.EnsureAnalyzed(node); 5055 analysis.EnsureAnalyzed(node);
5372 if (analysis.has_failed()) { 5056 if (analysis.has_failed()) {
5373 const char* error_message = analysis.error_message(); 5057 const char* error_message = analysis.error_message();
5374 return CompilationResult(zone->isolate(), error_message); 5058 return CompilationResult(error_message);
5375 } 5059 }
5376 5060
5377 // Create the correct assembler for the architecture.
5378 #ifndef V8_INTERPRETED_REGEXP
5379 // Native regexp implementation. 5061 // Native regexp implementation.
5380 5062
5381 NativeRegExpMacroAssembler::Mode mode = 5063 IRRegExpMacroAssembler* macro_assembler =
5382 is_one_byte ? NativeRegExpMacroAssembler::LATIN1 5064 new(isolate) IRRegExpMacroAssembler(specialization_cid,
5383 : NativeRegExpMacroAssembler::UC16; 5065 data->capture_count,
5384 5066 parsed_function,
5385 #if V8_TARGET_ARCH_IA32 5067 ic_data_array,
5386 RegExpMacroAssemblerIA32 macro_assembler(mode, (data->capture_count + 1) * 2, 5068 isolate);
5387 zone);
5388 #elif V8_TARGET_ARCH_X64
5389 RegExpMacroAssemblerX64 macro_assembler(mode, (data->capture_count + 1) * 2,
5390 zone);
5391 #elif V8_TARGET_ARCH_ARM
5392 RegExpMacroAssemblerARM macro_assembler(mode, (data->capture_count + 1) * 2,
5393 zone);
5394 #elif V8_TARGET_ARCH_ARM64
5395 RegExpMacroAssemblerARM64 macro_assembler(mode, (data->capture_count + 1) * 2,
5396 zone);
5397 #elif V8_TARGET_ARCH_MIPS
5398 RegExpMacroAssemblerMIPS macro_assembler(mode, (data->capture_count + 1) * 2,
5399 zone);
5400 #elif V8_TARGET_ARCH_MIPS64
5401 RegExpMacroAssemblerMIPS macro_assembler(mode, (data->capture_count + 1) * 2,
5402 zone);
5403 #elif V8_TARGET_ARCH_X87
5404 RegExpMacroAssemblerX87 macro_assembler(mode, (data->capture_count + 1) * 2,
5405 zone);
5406 #else
5407 #error "Unsupported architecture"
5408 #endif
5409
5410 #else // V8_INTERPRETED_REGEXP
5411 // Interpreted regexp implementation.
5412 EmbeddedVector<byte, 1024> codes;
5413 RegExpMacroAssemblerIrregexp macro_assembler(codes, zone);
5414 #endif // V8_INTERPRETED_REGEXP
5415 5069
5416 // Inserted here, instead of in Assembler, because it depends on information 5070 // Inserted here, instead of in Assembler, because it depends on information
5417 // in the AST that isn't replicated in the Node structure. 5071 // in the AST that isn't replicated in the Node structure.
5418 static const int kMaxBacksearchLimit = 1024; 5072 static const intptr_t kMaxBacksearchLimit = 1024;
5419 if (is_end_anchored && 5073 if (is_end_anchored &&
5420 !is_start_anchored && 5074 !is_start_anchored &&
5421 max_length < kMaxBacksearchLimit) { 5075 max_length < kMaxBacksearchLimit) {
5422 macro_assembler.SetCurrentPositionFromEnd(max_length); 5076 macro_assembler->SetCurrentPositionFromEnd(max_length);
5423 } 5077 }
5424 5078
5425 if (is_global) { 5079 if (is_global) {
5426 macro_assembler.set_global_mode( 5080 macro_assembler->set_global_mode(
5427 (data->tree->min_match() > 0) 5081 (data->tree->min_match() > 0)
5428 ? RegExpMacroAssembler::GLOBAL_NO_ZERO_LENGTH_CHECK 5082 ? RegExpMacroAssembler::GLOBAL_NO_ZERO_LENGTH_CHECK
5429 : RegExpMacroAssembler::GLOBAL); 5083 : RegExpMacroAssembler::GLOBAL);
5430 } 5084 }
5431 5085
5432 return compiler.Assemble(&macro_assembler, 5086 RegExpEngine::CompilationResult result =
5433 node, 5087 compiler.Assemble(macro_assembler,
5434 data->capture_count, 5088 node,
5435 pattern); 5089 data->capture_count,
5090 pattern);
5091
5092 if (FLAG_trace_irregexp) {
5093 macro_assembler->PrintBlocks();
5094 }
5095
5096 return result;
5436 } 5097 }
5437 5098
5099
5100 static void CreateSpecializedFunction(Isolate* isolate,
5101 const JSRegExp& regexp,
5102 intptr_t specialization_cid,
5103 const Object& owner) {
5104 const intptr_t kParamCount = RegExpMacroAssembler::kParamCount;
5105
5106 Function& fn = Function::Handle(isolate, Function::New(
5107 Symbols::IrregExp(),
5108 RawFunction::kIrregexpFunction,
5109 true, // Static.
5110 false, // Not const.
5111 false, // Not abstract.
5112 false, // Not external.
5113 false, // Not native.
5114 owner,
5115 0)); // No token position.
5116
5117 // TODO(zerny): Share these arrays between all irregexp functions.
5118 fn.set_num_fixed_parameters(kParamCount);
5119 fn.set_parameter_types(Array::Handle(isolate, Array::New(kParamCount,
5120 Heap::kOld)));
5121 fn.set_parameter_names(Array::Handle(isolate, Array::New(kParamCount,
5122 Heap::kOld)));
5123 fn.SetParameterTypeAt(0, Type::Handle(isolate, Type::DynamicType()));
5124 fn.SetParameterNameAt(0, Symbols::string_param());
5125 fn.SetParameterTypeAt(1, Type::Handle(isolate, Type::DynamicType()));
5126 fn.SetParameterNameAt(1, Symbols::start_index_param());
5127 fn.set_result_type(Type::Handle(isolate, Type::ArrayType()));
5128
5129 // Cache the result.
5130 regexp.set_function(specialization_cid, fn);
5131
5132 fn.set_regexp(regexp);
5133 fn.set_regexp_cid(specialization_cid);
5134
5135 // The function is compiled lazily during the first call.
5136 }
5137
5138
5139 RawJSRegExp* RegExpEngine::CreateJSRegExp(Isolate* isolate,
5140 const String& pattern,
5141 bool multi_line,
5142 bool ignore_case) {
5143 const JSRegExp& regexp = JSRegExp::Handle(JSRegExp::New(0));
5144
5145 regexp.set_pattern(pattern);
5146
5147 if (multi_line) {
5148 regexp.set_is_multi_line();
5149 }
5150 if (ignore_case) {
5151 regexp.set_is_ignore_case();
5152 }
5153
5154 // TODO(zerny): We might want to use normal string searching algorithms
5155 // for simple patterns.
5156 regexp.set_is_complex();
5157 regexp.set_is_global(); // All dart regexps are global.
5158
5159 const Library& lib = Library::Handle(isolate, Library::CoreLibrary());
5160 const Class& owner = Class::Handle(
5161 isolate, lib.LookupClass(Symbols::RegExp()));
5162
5163 CreateSpecializedFunction(isolate, regexp, kOneByteStringCid, owner);
5164 CreateSpecializedFunction(isolate, regexp, kTwoByteStringCid, owner);
5165 CreateSpecializedFunction(isolate, regexp, kExternalOneByteStringCid, owner);
5166 CreateSpecializedFunction(isolate, regexp, kExternalTwoByteStringCid, owner);
5167
5168 return regexp.raw();
5169 }
5170
5171
5438 } // namespace dart 5172 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/regexp.h ('k') | runtime/vm/regexp_assembler.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698