OLD | NEW |
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 #ifndef VM_REGEXP_ASSEMBLER_H_ | 5 #ifndef VM_REGEXP_ASSEMBLER_H_ |
6 #define VM_REGEXP_ASSEMBLER_H_ | 6 #define VM_REGEXP_ASSEMBLER_H_ |
7 | 7 |
8 #include "vm/assembler.h" | 8 #include "vm/assembler.h" |
9 #include "vm/intermediate_language.h" | 9 #include "vm/intermediate_language.h" |
10 #include "vm/object.h" | 10 #include "vm/object.h" |
11 | 11 |
12 namespace dart { | 12 namespace dart { |
13 | 13 |
14 // Utility function for the DotPrinter | 14 // Utility function for the DotPrinter |
15 void PrintUtf16(uint16_t c); | 15 void PrintUtf16(uint16_t c); |
16 | 16 |
17 | 17 |
18 /// Convenience wrapper around a BlockEntryInstr pointer. | 18 /// Convenience wrapper around a BlockEntryInstr pointer. |
19 class BlockLabel : public ValueObject { | 19 class BlockLabel : public ValueObject { |
| 20 // Used by the IR assembler. |
20 public: | 21 public: |
21 BlockLabel() | 22 BlockLabel() |
22 : block_(new JoinEntryInstr(-1, -1)), | 23 : block_(new JoinEntryInstr(-1, -1)), |
23 is_bound_(false), | 24 is_bound_(false), |
24 is_linked_(false) { } | 25 is_linked_(false), |
25 | 26 pos_(-1) { } |
26 BlockLabel(const BlockLabel& that) | |
27 : ValueObject(), | |
28 block_(that.block_), | |
29 is_bound_(that.is_bound_), | |
30 is_linked_(that.is_linked_) { } | |
31 | |
32 BlockLabel& operator=(const BlockLabel& that) { | |
33 block_ = that.block_; | |
34 is_bound_ = that.is_bound_; | |
35 is_linked_ = that.is_linked_; | |
36 return *this; | |
37 } | |
38 | 27 |
39 JoinEntryInstr* block() const { return block_; } | 28 JoinEntryInstr* block() const { return block_; } |
40 | 29 |
41 bool IsBound() const { return is_bound_; } | 30 bool IsBound() const { return is_bound_; } |
42 void SetBound(intptr_t block_id) { | 31 void SetBound(intptr_t block_id) { |
43 ASSERT(!is_bound_); | 32 ASSERT(!is_bound_); |
44 block_->set_block_id(block_id); | 33 block_->set_block_id(block_id); |
45 is_bound_ = true; | 34 is_bound_ = true; |
46 } | 35 } |
47 | 36 |
48 bool IsLinked() const { return !is_bound_ && is_linked_; } | 37 bool IsLinked() const { return !is_bound_ && is_linked_; } |
49 void SetLinked() { | 38 void SetLinked() { |
50 is_linked_ = true; | 39 is_linked_ = true; |
51 } | 40 } |
52 | 41 |
53 intptr_t Position() const { | 42 intptr_t Position() const { |
54 ASSERT(IsBound()); | 43 ASSERT(IsBound()); |
55 return block_->block_id(); | 44 return block_->block_id(); |
56 } | 45 } |
57 | 46 |
58 private: | 47 private: |
59 JoinEntryInstr* block_; | 48 JoinEntryInstr* block_; |
60 | 49 |
61 bool is_bound_; | 50 bool is_bound_; |
62 bool is_linked_; | 51 bool is_linked_; |
| 52 |
| 53 // Used by the bytecode assembler. |
| 54 public: |
| 55 ~BlockLabel() { |
| 56 ASSERT(!is_linked()); |
| 57 } |
| 58 |
| 59 intptr_t pos() const { |
| 60 return pos_; |
| 61 } |
| 62 bool is_bound() const { return IsBound(); } |
| 63 bool is_linked() const { return IsLinked(); } |
| 64 |
| 65 void Unuse() { |
| 66 pos_ = 0; |
| 67 is_bound_ = false; |
| 68 is_linked_ = false; |
| 69 } |
| 70 |
| 71 void bind_to(intptr_t pos) { |
| 72 pos_ = pos; |
| 73 is_bound_ = true; |
| 74 is_linked_ = false; |
| 75 ASSERT(is_bound()); |
| 76 } |
| 77 |
| 78 void link_to(intptr_t pos) { |
| 79 pos_ = pos; |
| 80 is_bound_ = false; |
| 81 is_linked_ = true; |
| 82 ASSERT(is_linked()); |
| 83 } |
| 84 |
| 85 private: |
| 86 intptr_t pos_; |
63 }; | 87 }; |
64 | 88 |
65 | 89 |
66 class RegExpMacroAssembler : public ZoneAllocated { | 90 class RegExpMacroAssembler : public ZoneAllocated { |
67 public: | 91 public: |
68 // The implementation must be able to handle at least: | 92 // The implementation must be able to handle at least: |
69 static const intptr_t kMaxRegister = (1 << 16) - 1; | 93 static const intptr_t kMaxRegister = (1 << 16) - 1; |
70 static const intptr_t kMaxCPOffset = (1 << 15) - 1; | 94 static const intptr_t kMaxCPOffset = (1 << 15) - 1; |
71 static const intptr_t kMinCPOffset = -(1 << 15); | 95 static const intptr_t kMinCPOffset = -(1 << 15); |
72 | 96 |
73 static const intptr_t kTableSizeBits = 7; | 97 static const intptr_t kTableSizeBits = 7; |
74 static const intptr_t kTableSize = 1 << kTableSizeBits; | 98 static const intptr_t kTableSize = 1 << kTableSizeBits; |
75 static const intptr_t kTableMask = kTableSize - 1; | 99 static const intptr_t kTableMask = kTableSize - 1; |
76 | 100 |
77 enum { | 101 enum { |
78 kParamStringIndex = 0, | 102 kParamStringIndex = 0, |
79 kParamStartOffsetIndex, | 103 kParamStartOffsetIndex, |
80 kParamCount | 104 kParamCount |
81 }; | 105 }; |
82 | 106 |
83 enum IrregexpImplementation { | 107 enum IrregexpImplementation { |
| 108 kBytecodeImplementation, |
84 kIRImplementation | 109 kIRImplementation |
85 }; | 110 }; |
86 | 111 |
87 explicit RegExpMacroAssembler(Zone* zone); | 112 explicit RegExpMacroAssembler(Zone* zone); |
88 virtual ~RegExpMacroAssembler(); | 113 virtual ~RegExpMacroAssembler(); |
89 // The maximal number of pushes between stack checks. Users must supply | 114 // The maximal number of pushes between stack checks. Users must supply |
90 // kCheckStackLimit flag to push operations (instead of kNoStackLimitCheck) | 115 // kCheckStackLimit flag to push operations (instead of kNoStackLimitCheck) |
91 // at least once for every stack_limit() pushes that are executed. | 116 // at least once for every stack_limit() pushes that are executed. |
92 virtual intptr_t stack_limit_slack() = 0; | 117 virtual intptr_t stack_limit_slack() = 0; |
93 virtual bool CanReadUnaligned() = 0; | 118 virtual bool CanReadUnaligned() = 0; |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
210 } | 235 } |
211 | 236 |
212 Zone* zone() const { return zone_; } | 237 Zone* zone() const { return zone_; } |
213 | 238 |
214 private: | 239 private: |
215 bool slow_safe_compiler_; | 240 bool slow_safe_compiler_; |
216 bool global_mode_; | 241 bool global_mode_; |
217 Zone* zone_; | 242 Zone* zone_; |
218 }; | 243 }; |
219 | 244 |
220 | |
221 class IRRegExpMacroAssembler : public RegExpMacroAssembler { | |
222 public: | |
223 // Type of input string to generate code for. | |
224 enum Mode { ASCII = 1, UC16 = 2 }; | |
225 | |
226 // Result of calling generated native RegExp code. | |
227 // RETRY: Something significant changed during execution, and the matching | |
228 // should be retried from scratch. | |
229 // EXCEPTION: Something failed during execution. If no exception has been | |
230 // thrown, it's an internal out-of-memory, and the caller should | |
231 // throw the exception. | |
232 // FAILURE: Matching failed. | |
233 // SUCCESS: Matching succeeded, and the output array has been filled with | |
234 // capture positions. | |
235 enum Result { RETRY = -2, EXCEPTION = -1, FAILURE = 0, SUCCESS = 1 }; | |
236 | |
237 IRRegExpMacroAssembler(intptr_t specialization_cid, | |
238 intptr_t capture_count, | |
239 const ParsedFunction* parsed_function, | |
240 const ZoneGrowableArray<const ICData*>& ic_data_array, | |
241 Zone* zone); | |
242 virtual ~IRRegExpMacroAssembler(); | |
243 | |
244 virtual bool CanReadUnaligned(); | |
245 | |
246 // Compares two-byte strings case insensitively. | |
247 // Called from generated RegExp code. | |
248 static RawBool* CaseInsensitiveCompareUC16( | |
249 RawString* str_raw, | |
250 RawSmi* lhs_index_raw, | |
251 RawSmi* rhs_index_raw, | |
252 RawSmi* length_raw); | |
253 | |
254 static RawArray* Execute(const Function& function, | |
255 const String& input, | |
256 const Smi& start_offset, | |
257 Zone* zone); | |
258 | |
259 virtual bool IsClosed() const { return (current_instruction_ == NULL); } | |
260 | |
261 virtual intptr_t stack_limit_slack(); | |
262 virtual void AdvanceCurrentPosition(intptr_t by); | |
263 virtual void AdvanceRegister(intptr_t reg, intptr_t by); | |
264 virtual void Backtrack(); | |
265 virtual void BindBlock(BlockLabel* label); | |
266 virtual void CheckAtStart(BlockLabel* on_at_start); | |
267 virtual void CheckCharacter(uint32_t c, BlockLabel* on_equal); | |
268 virtual void CheckCharacterAfterAnd(uint32_t c, | |
269 uint32_t mask, | |
270 BlockLabel* on_equal); | |
271 virtual void CheckCharacterGT(uint16_t limit, BlockLabel* on_greater); | |
272 virtual void CheckCharacterLT(uint16_t limit, BlockLabel* on_less); | |
273 // A "greedy loop" is a loop that is both greedy and with a simple | |
274 // body. It has a particularly simple implementation. | |
275 virtual void CheckGreedyLoop(BlockLabel* on_tos_equals_current_position); | |
276 virtual void CheckNotAtStart(BlockLabel* on_not_at_start); | |
277 virtual void CheckNotBackReference(intptr_t start_reg, | |
278 BlockLabel* on_no_match); | |
279 virtual void CheckNotBackReferenceIgnoreCase(intptr_t start_reg, | |
280 BlockLabel* on_no_match); | |
281 virtual void CheckNotCharacter(uint32_t c, BlockLabel* on_not_equal); | |
282 virtual void CheckNotCharacterAfterAnd(uint32_t c, | |
283 uint32_t mask, | |
284 BlockLabel* on_not_equal); | |
285 virtual void CheckNotCharacterAfterMinusAnd(uint16_t c, | |
286 uint16_t minus, | |
287 uint16_t mask, | |
288 BlockLabel* on_not_equal); | |
289 virtual void CheckCharacterInRange(uint16_t from, | |
290 uint16_t to, | |
291 BlockLabel* on_in_range); | |
292 virtual void CheckCharacterNotInRange(uint16_t from, | |
293 uint16_t to, | |
294 BlockLabel* on_not_in_range); | |
295 virtual void CheckBitInTable(const TypedData& table, BlockLabel* on_bit_set); | |
296 | |
297 // Checks whether the given offset from the current position is before | |
298 // the end of the string. | |
299 virtual void CheckPosition(intptr_t cp_offset, BlockLabel* on_outside_input); | |
300 virtual bool CheckSpecialCharacterClass( | |
301 uint16_t type, BlockLabel* on_no_match); | |
302 virtual void Fail(); | |
303 virtual void IfRegisterGE(intptr_t reg, | |
304 intptr_t comparand, BlockLabel* if_ge); | |
305 virtual void IfRegisterLT(intptr_t reg, | |
306 intptr_t comparand, BlockLabel* if_lt); | |
307 virtual void IfRegisterEqPos(intptr_t reg, BlockLabel* if_eq); | |
308 virtual IrregexpImplementation Implementation(); | |
309 virtual void GoTo(BlockLabel* to); | |
310 virtual void LoadCurrentCharacter(intptr_t cp_offset, | |
311 BlockLabel* on_end_of_input, | |
312 bool check_bounds = true, | |
313 intptr_t characters = 1); | |
314 virtual void PopCurrentPosition(); | |
315 virtual void PopRegister(intptr_t register_index); | |
316 virtual void Print(const char* str); | |
317 virtual void PushBacktrack(BlockLabel* label); | |
318 virtual void PushCurrentPosition(); | |
319 virtual void PushRegister(intptr_t register_index); | |
320 virtual void ReadCurrentPositionFromRegister(intptr_t reg); | |
321 virtual void ReadStackPointerFromRegister(intptr_t reg); | |
322 virtual void SetCurrentPositionFromEnd(intptr_t by); | |
323 virtual void SetRegister(intptr_t register_index, intptr_t to); | |
324 virtual bool Succeed(); | |
325 virtual void WriteCurrentPositionToRegister(intptr_t reg, intptr_t cp_offset); | |
326 virtual void ClearRegisters(intptr_t reg_from, intptr_t reg_to); | |
327 virtual void WriteStackPointerToRegister(intptr_t reg); | |
328 | |
329 virtual void PrintBlocks(); | |
330 | |
331 IndirectGotoInstr* backtrack_goto() const { return backtrack_goto_; } | |
332 GraphEntryInstr* graph_entry() const { return entry_block_; } | |
333 | |
334 intptr_t num_stack_locals() const { return local_id_.Count(); } | |
335 intptr_t num_blocks() const { return block_id_.Count(); } | |
336 | |
337 // Generate a dispatch block implementing backtracking. Must be done after | |
338 // graph construction. | |
339 void GenerateBacktrackBlock(); | |
340 | |
341 // Allocate the actual registers array once its size is known. Must be done | |
342 // after graph construction. | |
343 void FinalizeRegistersArray(); | |
344 | |
345 private: | |
346 // Generate the contents of preset blocks. The entry block is the entry point | |
347 // of the generated code. | |
348 void GenerateEntryBlock(); | |
349 // Copies capture indices into the result area and returns true. | |
350 void GenerateSuccessBlock(); | |
351 // Returns false. | |
352 void GenerateExitBlock(); | |
353 | |
354 enum ComparisonKind { | |
355 kEQ, | |
356 kNE, | |
357 kLT, | |
358 kGT, | |
359 kLTE, | |
360 kGTE, | |
361 }; | |
362 | |
363 struct InstanceCallDescriptor { | |
364 // Standard (i.e. most non-Smi) functions. | |
365 explicit InstanceCallDescriptor(const String& name) | |
366 : name(name), | |
367 token_kind(Token::kILLEGAL), | |
368 checked_argument_count(1) { } | |
369 | |
370 InstanceCallDescriptor(const String& name, | |
371 Token::Kind token_kind, | |
372 intptr_t checked_argument_count) | |
373 : name(name), | |
374 token_kind(token_kind), | |
375 checked_argument_count(checked_argument_count) { } | |
376 | |
377 // Special cases for Smi and indexing functions. | |
378 static InstanceCallDescriptor FromToken(Token::Kind token_kind) { | |
379 switch (token_kind) { | |
380 case Token::kEQ: return InstanceCallDescriptor( | |
381 Symbols::EqualOperator(), token_kind, 2); | |
382 case Token::kADD: return InstanceCallDescriptor( | |
383 Symbols::Plus(), token_kind, 2); | |
384 case Token::kSUB: return InstanceCallDescriptor( | |
385 Symbols::Minus(), token_kind, 2); | |
386 case Token::kBIT_OR: return InstanceCallDescriptor( | |
387 Symbols::BitOr(), token_kind, 2); | |
388 case Token::kBIT_AND: return InstanceCallDescriptor( | |
389 Symbols::BitAnd(), token_kind, 2); | |
390 case Token::kLT: return InstanceCallDescriptor( | |
391 Symbols::LAngleBracket(), token_kind, 2); | |
392 case Token::kLTE: return InstanceCallDescriptor( | |
393 Symbols::LessEqualOperator(), token_kind, 2); | |
394 case Token::kGT: return InstanceCallDescriptor( | |
395 Symbols::RAngleBracket(), token_kind, 2); | |
396 case Token::kGTE: return InstanceCallDescriptor( | |
397 Symbols::GreaterEqualOperator(), token_kind, 2); | |
398 case Token::kNEGATE: return InstanceCallDescriptor( | |
399 Symbols::UnaryMinus(), token_kind, 1); | |
400 case Token::kINDEX: return InstanceCallDescriptor( | |
401 Symbols::IndexToken(), token_kind, 2); | |
402 case Token::kASSIGN_INDEX: return InstanceCallDescriptor( | |
403 Symbols::AssignIndexToken(), token_kind, 2); | |
404 default: | |
405 UNREACHABLE(); | |
406 } | |
407 UNREACHABLE(); | |
408 return InstanceCallDescriptor(Symbols::Empty()); | |
409 } | |
410 | |
411 const String& name; | |
412 Token::Kind token_kind; | |
413 intptr_t checked_argument_count; | |
414 }; | |
415 | |
416 LocalVariable* Local(const String& name); | |
417 LocalVariable* Parameter(const String& name, intptr_t index) const; | |
418 | |
419 ConstantInstr* Int64Constant(int64_t value) const; | |
420 ConstantInstr* Uint64Constant(uint64_t value) const; | |
421 ConstantInstr* BoolConstant(bool value) const; | |
422 ConstantInstr* StringConstant(const char* value) const; | |
423 | |
424 // The word character map static member of the RegExp class. | |
425 // Byte map of one byte characters with a 0xff if the character is a word | |
426 // character (digit, letter or underscore) and 0x00 otherwise. | |
427 // Used by generated RegExp code. | |
428 ConstantInstr* WordCharacterMapConstant() const; | |
429 | |
430 ComparisonInstr* Comparison(ComparisonKind kind, | |
431 PushArgumentInstr* lhs, | |
432 PushArgumentInstr* rhs); | |
433 ComparisonInstr* Comparison(ComparisonKind kind, | |
434 Definition* lhs, | |
435 Definition* rhs); | |
436 | |
437 InstanceCallInstr* InstanceCall(const InstanceCallDescriptor& desc, | |
438 PushArgumentInstr* arg1) const; | |
439 InstanceCallInstr* InstanceCall(const InstanceCallDescriptor& desc, | |
440 PushArgumentInstr* arg1, | |
441 PushArgumentInstr* arg2) const; | |
442 InstanceCallInstr* InstanceCall(const InstanceCallDescriptor& desc, | |
443 PushArgumentInstr* arg1, | |
444 PushArgumentInstr* arg2, | |
445 PushArgumentInstr* arg3) const; | |
446 InstanceCallInstr* InstanceCall( | |
447 const InstanceCallDescriptor& desc, | |
448 ZoneGrowableArray<PushArgumentInstr*>* arguments) const; | |
449 | |
450 StaticCallInstr* StaticCall(const Function& function) const; | |
451 StaticCallInstr* StaticCall(const Function& function, | |
452 PushArgumentInstr* arg1) const; | |
453 StaticCallInstr* StaticCall(const Function& function, | |
454 PushArgumentInstr* arg1, | |
455 PushArgumentInstr* arg2) const; | |
456 StaticCallInstr* StaticCall( | |
457 const Function& function, | |
458 ZoneGrowableArray<PushArgumentInstr*>* arguments) const; | |
459 | |
460 // Creates a new block consisting simply of a goto to dst. | |
461 TargetEntryInstr* TargetWithJoinGoto(JoinEntryInstr* dst); | |
462 IndirectEntryInstr* IndirectWithJoinGoto(JoinEntryInstr* dst); | |
463 | |
464 // Adds, respectively subtracts lhs and rhs and returns the result. | |
465 Definition* Add(PushArgumentInstr* lhs, PushArgumentInstr* rhs); | |
466 Definition* Sub(PushArgumentInstr* lhs, PushArgumentInstr* rhs); | |
467 | |
468 LoadLocalInstr* LoadLocal(LocalVariable* local) const; | |
469 void StoreLocal(LocalVariable* local, Value* value); | |
470 | |
471 PushArgumentInstr* PushArgument(Value* value); | |
472 PushArgumentInstr* PushLocal(LocalVariable* local); | |
473 | |
474 PushArgumentInstr* PushRegisterIndex(intptr_t reg); | |
475 Value* LoadRegister(intptr_t reg); | |
476 void StoreRegister(intptr_t reg, intptr_t value); | |
477 void StoreRegister(PushArgumentInstr* registers, | |
478 PushArgumentInstr* index, | |
479 PushArgumentInstr* value); | |
480 | |
481 // Load a number of characters at the given offset from the | |
482 // current position, into the current-character register. | |
483 void LoadCurrentCharacterUnchecked(intptr_t cp_offset, | |
484 intptr_t character_count); | |
485 | |
486 // Returns the character within the passed string at the specified index. | |
487 Value* CharacterAt(LocalVariable* index); | |
488 | |
489 // Load a number of characters starting from index in the pattern string. | |
490 Value* LoadCodeUnitsAt(LocalVariable* index, intptr_t character_count); | |
491 | |
492 // Check whether preemption has been requested. | |
493 void CheckPreemption(); | |
494 | |
495 // Byte size of chars in the string to match (decided by the Mode argument) | |
496 inline intptr_t char_size() { return static_cast<int>(mode_); } | |
497 | |
498 // Equivalent to a conditional branch to the label, unless the label | |
499 // is NULL, in which case it is a conditional Backtrack. | |
500 void BranchOrBacktrack(ComparisonInstr* comparison, | |
501 BlockLabel* true_successor); | |
502 | |
503 // Set up all local variables and parameters. | |
504 void InitializeLocals(); | |
505 | |
506 // Allocates a new local, and returns the appropriate id for placing it | |
507 // on the stack. | |
508 intptr_t GetNextLocalIndex(); | |
509 | |
510 // We never have any copied parameters. | |
511 intptr_t num_copied_params() const { | |
512 return 0; | |
513 } | |
514 | |
515 // Return the position register at the specified index, creating it if | |
516 // necessary. Note that the number of such registers can exceed the amount | |
517 // required by the number of output captures. | |
518 LocalVariable* position_register(intptr_t index); | |
519 | |
520 void set_current_instruction(Instruction* instruction); | |
521 | |
522 // The following functions are responsible for appending instructions | |
523 // to the current instruction in various ways. The most simple one | |
524 // is AppendInstruction, which simply appends an instruction and performs | |
525 // bookkeeping. | |
526 void AppendInstruction(Instruction* instruction); | |
527 // Similar to AppendInstruction, but closes the current block by | |
528 // setting current_instruction_ to NULL. | |
529 void CloseBlockWith(Instruction* instruction); | |
530 // Appends definition and allocates a temp index for the result. | |
531 Value* Bind(Definition* definition); | |
532 // Loads and binds a local variable. | |
533 Value* BindLoadLocal(const LocalVariable& local); | |
534 | |
535 // Appends the definition. | |
536 void Do(Definition* definition); | |
537 // Closes the current block with a jump to the specified block. | |
538 void GoTo(JoinEntryInstr* to); | |
539 | |
540 // Accessors for our local stack_. | |
541 void PushStack(Definition* definition); | |
542 Definition* PopStack(); | |
543 Definition* PeekStack(); | |
544 void CheckStackLimit(); | |
545 void GrowStack(); | |
546 | |
547 // Prints the specified argument. Used for debugging. | |
548 void Print(PushArgumentInstr* argument); | |
549 | |
550 // A utility class tracking ids of various objects such as blocks, temps, etc. | |
551 class IdAllocator : public ValueObject { | |
552 public: | |
553 IdAllocator() : next_id(0) { } | |
554 | |
555 intptr_t Count() const { return next_id; } | |
556 intptr_t Alloc(intptr_t count = 1) { | |
557 ASSERT(count >= 0); | |
558 intptr_t current_id = next_id; | |
559 next_id += count; | |
560 return current_id; | |
561 } | |
562 void Dealloc(intptr_t count = 1) { | |
563 ASSERT(count <= next_id); | |
564 next_id -= count; | |
565 } | |
566 | |
567 private: | |
568 intptr_t next_id; | |
569 }; | |
570 | |
571 // Which mode to generate code for (ASCII or UC16). | |
572 Mode mode_; | |
573 | |
574 // Which specific string class to generate code for. | |
575 intptr_t specialization_cid_; | |
576 | |
577 // Block entries used internally. | |
578 GraphEntryInstr* entry_block_; | |
579 JoinEntryInstr* start_block_; | |
580 JoinEntryInstr* success_block_; | |
581 JoinEntryInstr* exit_block_; | |
582 | |
583 // Shared backtracking block. | |
584 JoinEntryInstr* backtrack_block_; | |
585 // Single indirect goto instruction which performs all backtracking. | |
586 IndirectGotoInstr* backtrack_goto_; | |
587 | |
588 const ParsedFunction* parsed_function_; | |
589 const ZoneGrowableArray<const ICData*>& ic_data_array_; | |
590 | |
591 // All created blocks are contained within this set. Used for printing | |
592 // the generated code. | |
593 GrowableArray<BlockEntryInstr*> blocks_; | |
594 | |
595 // The current instruction to link to when new code is emitted. | |
596 Instruction* current_instruction_; | |
597 | |
598 // A list, acting as the runtime stack for both backtrack locations and | |
599 // stored positions within the string. | |
600 LocalVariable* stack_; | |
601 LocalVariable* stack_pointer_; | |
602 | |
603 // Stores the current character within the string. | |
604 LocalVariable* current_character_; | |
605 | |
606 // Stores the current location within the string as a negative offset | |
607 // from the end of the string. | |
608 LocalVariable* current_position_; | |
609 | |
610 // The string being processed, passed as a function parameter. | |
611 LocalVariable* string_param_; | |
612 | |
613 // Stores the length of string_param_. | |
614 LocalVariable* string_param_length_; | |
615 | |
616 // The start index within the string, passed as a function parameter. | |
617 LocalVariable* start_index_param_; | |
618 | |
619 // An assortment of utility variables. | |
620 LocalVariable* capture_length_; | |
621 LocalVariable* match_start_index_; | |
622 LocalVariable* capture_start_index_; | |
623 LocalVariable* match_end_index_; | |
624 LocalVariable* char_in_capture_; | |
625 LocalVariable* char_in_match_; | |
626 LocalVariable* index_temp_; | |
627 | |
628 LocalVariable* result_; | |
629 | |
630 // Stored positions containing group bounds. Generated as needed. | |
631 LocalVariable* registers_; | |
632 intptr_t registers_count_; | |
633 const intptr_t saved_registers_count_; | |
634 | |
635 // The actual array objects used for the stack and registers. | |
636 Array& stack_array_cell_; | |
637 TypedData& registers_array_; | |
638 | |
639 IdAllocator block_id_; | |
640 IdAllocator temp_id_; | |
641 IdAllocator arg_id_; | |
642 IdAllocator local_id_; | |
643 IdAllocator indirect_id_; | |
644 }; | |
645 | |
646 | |
647 } // namespace dart | 245 } // namespace dart |
648 | 246 |
649 #endif // VM_REGEXP_ASSEMBLER_H_ | 247 #endif // VM_REGEXP_ASSEMBLER_H_ |
OLD | NEW |