OLD | NEW |
---|---|
(Empty) | |
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 | |
3 // BSD-style license that can be found in the LICENSE file. | |
4 | |
5 #ifndef VM_REGEXP_ASSEMBLER_H_ | |
6 #define VM_REGEXP_ASSEMBLER_H_ | |
7 | |
8 #include "vm/assembler.h" | |
9 #include "vm/intermediate_language.h" | |
10 #include "vm/object.h" | |
11 | |
12 namespace dart { | |
13 | |
14 /// Convenience wrapper around a BlockEntryInstr pointer. | |
15 class BlockLabel : public ValueObject { | |
16 public: | |
17 BlockLabel() | |
18 : block_(new JoinEntryInstr(-1, -1)), | |
19 is_bound_(false), | |
20 is_linked_(false) { } | |
21 | |
22 BlockLabel(const BlockLabel& that) | |
23 : ValueObject(), | |
24 block_(that.block_), | |
25 is_bound_(that.is_bound_), | |
26 is_linked_(that.is_linked_) { } | |
27 | |
28 BlockLabel& operator=(const BlockLabel& that) { | |
29 block_ = that.block_; | |
30 is_bound_ = that.is_bound_; | |
31 is_linked_ = that.is_linked_; | |
32 return *this; | |
33 } | |
34 | |
35 JoinEntryInstr* block() const { return block_; } | |
36 | |
37 bool IsBound() const { return is_bound_; } | |
38 void SetBound(intptr_t block_id) { | |
39 ASSERT(!is_bound_); | |
40 block_->set_block_id(block_id); | |
41 is_bound_ = true; | |
42 } | |
43 | |
44 bool IsLinked() const { return !is_bound_ && is_linked_; } | |
45 void SetLinked() { | |
46 is_linked_ = true; | |
47 } | |
48 | |
49 intptr_t Position() const { | |
50 ASSERT(IsBound()); | |
51 return block_->block_id(); | |
52 } | |
53 | |
54 private: | |
55 JoinEntryInstr* block_; | |
56 | |
57 bool is_bound_; | |
58 bool is_linked_; | |
59 }; | |
60 | |
61 | |
62 class RegExpMacroAssembler : public ZoneAllocated { | |
63 public: | |
64 // The implementation must be able to handle at least: | |
65 static const intptr_t kMaxRegister = (1 << 16) - 1; | |
66 static const intptr_t kMaxCPOffset = (1 << 15) - 1; | |
67 static const intptr_t kMinCPOffset = -(1 << 15); | |
68 | |
69 static const intptr_t kTableSizeBits = 7; | |
70 static const intptr_t kTableSize = 1 << kTableSizeBits; | |
71 static const intptr_t kTableMask = kTableSize - 1; | |
72 | |
73 enum { | |
74 kParamStringIndex = 0, | |
75 kParamStartOffsetIndex, | |
76 kParamCount | |
77 }; | |
78 | |
79 enum IrregexpImplementation { | |
80 kIRImplementation | |
81 }; | |
82 | |
83 explicit RegExpMacroAssembler(Isolate* isolate); | |
84 virtual ~RegExpMacroAssembler(); | |
85 // The maximal number of pushes between stack checks. Users must supply | |
86 // kCheckStackLimit flag to push operations (instead of kNoStackLimitCheck) | |
87 // at least once for every stack_limit() pushes that are executed. | |
88 virtual intptr_t stack_limit_slack() = 0; | |
89 virtual bool CanReadUnaligned() = 0; | |
90 virtual void AdvanceCurrentPosition(intptr_t by) = 0; // Signed cp change. | |
91 virtual void AdvanceRegister(intptr_t reg, intptr_t by) = 0; // r[reg] += by. | |
92 // Continues execution from the position pushed on the top of the backtrack | |
93 // stack by an earlier PushBacktrack(BlockLabel*). | |
94 virtual void Backtrack() = 0; | |
95 virtual void BindBlock(BlockLabel* label) = 0; | |
96 virtual void CheckAtStart(BlockLabel* on_at_start) = 0; | |
97 // Dispatch after looking the current character up in a 2-bits-per-entry | |
98 // map. The destinations vector has up to 4 labels. | |
99 virtual void CheckCharacter(unsigned c, BlockLabel* on_equal) = 0; | |
100 // Bitwise and the current character with the given constant and then | |
101 // check for a match with c. | |
102 virtual void CheckCharacterAfterAnd(unsigned c, | |
103 unsigned and_with, | |
104 BlockLabel* on_equal) = 0; | |
105 virtual void CheckCharacterGT(uint16_t limit, BlockLabel* on_greater) = 0; | |
106 virtual void CheckCharacterLT(uint16_t limit, BlockLabel* on_less) = 0; | |
107 virtual void CheckGreedyLoop(BlockLabel* on_tos_equals_current_position) = 0; | |
108 virtual void CheckNotAtStart(BlockLabel* on_not_at_start) = 0; | |
109 virtual void CheckNotBackReference( | |
110 intptr_t start_reg, BlockLabel* on_no_match) = 0; | |
111 virtual void CheckNotBackReferenceIgnoreCase(intptr_t start_reg, | |
112 BlockLabel* on_no_match) = 0; | |
113 // Check the current character for a match with a literal character. If we | |
114 // fail to match then goto the on_failure label. End of input always | |
115 // matches. If the label is NULL then we should pop a backtrack address off | |
116 // the stack and go to that. | |
117 virtual void CheckNotCharacter(unsigned c, BlockLabel* on_not_equal) = 0; | |
118 virtual void CheckNotCharacterAfterAnd(unsigned c, | |
119 unsigned and_with, | |
120 BlockLabel* on_not_equal) = 0; | |
121 // Subtract a constant from the current character, then and with the given | |
122 // constant and then check for a match with c. | |
123 virtual void CheckNotCharacterAfterMinusAnd(uint16_t c, | |
124 uint16_t minus, | |
125 uint16_t and_with, | |
126 BlockLabel* on_not_equal) = 0; | |
127 virtual void CheckCharacterInRange(uint16_t from, | |
128 uint16_t to, // Both inclusive. | |
129 BlockLabel* on_in_range) = 0; | |
130 virtual void CheckCharacterNotInRange(uint16_t from, | |
131 uint16_t to, // Both inclusive. | |
132 BlockLabel* on_not_in_range) = 0; | |
133 | |
134 // The current character (modulus the kTableSize) is looked up in the byte | |
135 // array, and if the found byte is non-zero, we jump to the on_bit_set label. | |
136 virtual void CheckBitInTable(const TypedData& table, | |
137 BlockLabel* on_bit_set) = 0; | |
138 | |
139 // Checks whether the given offset from the current position is before | |
140 // the end of the string. May overwrite the current character. | |
141 virtual void CheckPosition(intptr_t cp_offset, BlockLabel* on_outside_input) { | |
142 LoadCurrentCharacter(cp_offset, on_outside_input, true); | |
143 } | |
144 // Check whether a standard/default character class matches the current | |
145 // character. Returns false if the type of special character class does | |
146 // not have custom support. | |
147 // May clobber the current loaded character. | |
148 virtual bool CheckSpecialCharacterClass(uint16_t type, | |
149 BlockLabel* on_no_match) { | |
150 return false; | |
151 } | |
152 virtual void Fail() = 0; | |
153 // Check whether a register is >= a given constant and go to a label if it | |
154 // is. Backtracks instead if the label is NULL. | |
155 virtual void IfRegisterGE( | |
156 intptr_t reg, intptr_t comparand, BlockLabel* if_ge) = 0; | |
157 // Check whether a register is < a given constant and go to a label if it is. | |
158 // Backtracks instead if the label is NULL. | |
159 virtual void IfRegisterLT( | |
160 intptr_t reg, intptr_t comparand, BlockLabel* if_lt) = 0; | |
161 // Check whether a register is == to the current position and go to a | |
162 // label if it is. | |
163 virtual void IfRegisterEqPos(intptr_t reg, BlockLabel* if_eq) = 0; | |
164 virtual IrregexpImplementation Implementation() = 0; | |
165 // The assembler is closed, iff there is no current instruction assigned. | |
166 virtual bool IsClosed() const = 0; | |
167 // Jump to the target label without setting it as the current instruction. | |
168 virtual void GoTo(BlockLabel* to) = 0; | |
169 virtual void LoadCurrentCharacter(intptr_t cp_offset, | |
170 BlockLabel* on_end_of_input, | |
171 bool check_bounds = true, | |
172 intptr_t characters = 1) = 0; | |
173 virtual void PopCurrentPosition() = 0; | |
174 virtual void PopRegister(intptr_t register_index) = 0; | |
175 // Prints string within the generated code. Used for debugging. | |
176 virtual void Print(const char* str) = 0; | |
177 // Prints all emitted blocks. | |
178 virtual void PrintBlocks() = 0; | |
179 // Pushes the label on the backtrack stack, so that a following Backtrack | |
180 // will go to this label. Always checks the backtrack stack limit. | |
181 virtual void PushBacktrack(BlockLabel* label) = 0; | |
182 virtual void PushCurrentPosition() = 0; | |
183 virtual void PushRegister(intptr_t register_index) = 0; | |
184 virtual void ReadCurrentPositionFromRegister(intptr_t reg) = 0; | |
185 virtual void ReadStackPointerFromRegister(intptr_t reg) = 0; | |
186 virtual void SetCurrentPositionFromEnd(intptr_t by) = 0; | |
187 virtual void SetRegister(intptr_t register_index, intptr_t to) = 0; | |
188 // Return whether the matching (with a global regexp) will be restarted. | |
189 virtual bool Succeed() = 0; | |
190 virtual void WriteCurrentPositionToRegister( | |
191 intptr_t reg, intptr_t cp_offset) = 0; | |
192 virtual void ClearRegisters(intptr_t reg_from, intptr_t reg_to) = 0; | |
193 virtual void WriteStackPointerToRegister(intptr_t reg) = 0; | |
194 | |
195 // Controls the generation of large inlined constants in the code. | |
196 void set_slow_safe(bool ssc) { slow_safe_compiler_ = ssc; } | |
197 bool slow_safe() { return slow_safe_compiler_; } | |
198 | |
199 enum GlobalMode { NOT_GLOBAL, GLOBAL, GLOBAL_NO_ZERO_LENGTH_CHECK }; | |
200 // Set whether the regular expression has the global flag. Exiting due to | |
201 // a failure in a global regexp may still mean success overall. | |
202 inline void set_global_mode(GlobalMode mode) { global_mode_ = mode; } | |
203 inline bool global() { return global_mode_ != NOT_GLOBAL; } | |
204 inline bool global_with_zero_length_check() { | |
205 return global_mode_ == GLOBAL; | |
206 } | |
207 | |
208 Isolate* isolate() const { return isolate_; } | |
209 | |
210 private: | |
211 bool slow_safe_compiler_; | |
212 bool global_mode_; | |
213 Isolate* isolate_; | |
214 }; | |
215 | |
216 | |
217 class IRRegExpMacroAssembler: public RegExpMacroAssembler { | |
218 public: | |
219 // Type of input string to generate code for. | |
220 enum Mode { ASCII = 1, UC16 = 2 }; | |
221 | |
222 // Result of calling generated native RegExp code. | |
223 // RETRY: Something significant changed during execution, and the matching | |
224 // should be retried from scratch. | |
225 // EXCEPTION: Something failed during execution. If no exception has been | |
226 // thrown, it's an internal out-of-memory, and the caller should | |
227 // throw the exception. | |
228 // FAILURE: Matching failed. | |
229 // SUCCESS: Matching succeeded, and the output array has been filled with | |
230 // capture positions. | |
231 enum Result { RETRY = -2, EXCEPTION = -1, FAILURE = 0, SUCCESS = 1 }; | |
232 | |
233 IRRegExpMacroAssembler(intptr_t specialization_cid, | |
234 intptr_t capture_count, | |
235 const ParsedFunction* parsed_function, | |
236 ZoneGrowableArray<const ICData*>* ic_data_array, | |
237 Isolate* isolate); | |
238 virtual ~IRRegExpMacroAssembler(); | |
239 | |
240 virtual bool CanReadUnaligned(); | |
241 | |
242 // Compares two-byte strings case insensitively. | |
243 // Called from generated RegExp code. | |
244 static RawBool* CaseInsensitiveCompareUC16( | |
245 RawString* str_raw, | |
246 RawSmi* lhs_index_raw, | |
247 RawSmi* rhs_index_raw, | |
248 RawSmi* length_raw); | |
249 | |
250 static RawArray* Execute(const Function& function, | |
251 const String& input, | |
252 const Smi& start_offset, | |
253 Isolate* isolate); | |
254 | |
255 virtual bool IsClosed() const { return (current_instruction_ == NULL); } | |
256 | |
257 virtual intptr_t stack_limit_slack(); | |
258 virtual void AdvanceCurrentPosition(intptr_t by); | |
259 virtual void AdvanceRegister(intptr_t reg, intptr_t by); | |
260 virtual void Backtrack(); | |
261 virtual void BindBlock(BlockLabel* label); | |
262 virtual void CheckAtStart(BlockLabel* on_at_start); | |
263 virtual void CheckCharacter(uint32_t c, BlockLabel* on_equal); | |
264 virtual void CheckCharacterAfterAnd(uint32_t c, | |
265 uint32_t mask, | |
266 BlockLabel* on_equal); | |
267 virtual void CheckCharacterGT(uint16_t limit, BlockLabel* on_greater); | |
268 virtual void CheckCharacterLT(uint16_t limit, BlockLabel* on_less); | |
269 // A "greedy loop" is a loop that is both greedy and with a simple | |
270 // body. It has a particularly simple implementation. | |
271 virtual void CheckGreedyLoop(BlockLabel* on_tos_equals_current_position); | |
272 virtual void CheckNotAtStart(BlockLabel* on_not_at_start); | |
273 virtual void CheckNotBackReference(intptr_t start_reg, | |
274 BlockLabel* on_no_match); | |
275 virtual void CheckNotBackReferenceIgnoreCase(intptr_t start_reg, | |
276 BlockLabel* on_no_match); | |
277 virtual void CheckNotCharacter(uint32_t c, BlockLabel* on_not_equal); | |
278 virtual void CheckNotCharacterAfterAnd(uint32_t c, | |
279 uint32_t mask, | |
280 BlockLabel* on_not_equal); | |
281 virtual void CheckNotCharacterAfterMinusAnd(uint16_t c, | |
282 uint16_t minus, | |
283 uint16_t mask, | |
284 BlockLabel* on_not_equal); | |
285 virtual void CheckCharacterInRange(uint16_t from, | |
286 uint16_t to, | |
287 BlockLabel* on_in_range); | |
288 virtual void CheckCharacterNotInRange(uint16_t from, | |
289 uint16_t to, | |
290 BlockLabel* on_not_in_range); | |
291 virtual void CheckBitInTable(const TypedData& table, BlockLabel* on_bit_set); | |
292 | |
293 // Checks whether the given offset from the current position is before | |
294 // the end of the string. | |
295 virtual void CheckPosition(intptr_t cp_offset, BlockLabel* on_outside_input); | |
296 virtual bool CheckSpecialCharacterClass( | |
297 uint16_t type, BlockLabel* on_no_match); | |
298 virtual void Fail(); | |
299 virtual void IfRegisterGE(intptr_t reg, | |
300 intptr_t comparand, BlockLabel* if_ge); | |
301 virtual void IfRegisterLT(intptr_t reg, | |
302 intptr_t comparand, BlockLabel* if_lt); | |
303 virtual void IfRegisterEqPos(intptr_t reg, BlockLabel* if_eq); | |
304 virtual IrregexpImplementation Implementation(); | |
305 virtual void GoTo(BlockLabel* to); | |
306 virtual void LoadCurrentCharacter(intptr_t cp_offset, | |
307 BlockLabel* on_end_of_input, | |
308 bool check_bounds = true, | |
309 intptr_t characters = 1); | |
310 virtual void PopCurrentPosition(); | |
311 virtual void PopRegister(intptr_t register_index); | |
312 virtual void Print(const char* str); | |
313 virtual void PushBacktrack(BlockLabel* label); | |
314 virtual void PushCurrentPosition(); | |
315 virtual void PushRegister(intptr_t register_index); | |
316 virtual void ReadCurrentPositionFromRegister(intptr_t reg); | |
317 virtual void ReadStackPointerFromRegister(intptr_t reg); | |
318 virtual void SetCurrentPositionFromEnd(intptr_t by); | |
319 virtual void SetRegister(intptr_t register_index, intptr_t to); | |
320 virtual bool Succeed(); | |
321 virtual void WriteCurrentPositionToRegister(intptr_t reg, intptr_t cp_offset); | |
322 virtual void ClearRegisters(intptr_t reg_from, intptr_t reg_to); | |
323 virtual void WriteStackPointerToRegister(intptr_t reg); | |
324 | |
325 virtual void PrintBlocks(); | |
326 | |
327 GraphEntryInstr* graph_entry() const { return entry_block_; } | |
328 | |
329 intptr_t num_stack_locals() const { return local_id.Count(); } | |
330 intptr_t num_blocks() const { return block_id.Count(); } | |
331 | |
332 // A table mapping block ids to block offsets, used to look up offsets | |
333 // for indirect goto instructions. | |
334 void FinalizeBlockOffsetTable(); | |
335 | |
336 // Fill in indirect goto successors. | |
337 void FinalizeIndirectGotos(); | |
338 | |
339 private: | |
340 // Generate the contents of preset blocks. The entry block is the entry point | |
341 // of the generated code. | |
342 void GenerateEntryBlock(); | |
343 // Performs backtracking, i.e. popping an offset from the stack and doing | |
344 // an indirect goto. | |
345 void GenerateBacktrackBlock(); | |
346 // Copies capture indices into the result area and returns true. | |
347 void GenerateSuccessBlock(); | |
348 // Returns false. | |
349 void GenerateExitBlock(); | |
350 | |
351 enum ComparisonKind { | |
352 kEQ, | |
353 kNE, | |
354 kLT, | |
355 kGT, | |
356 kLTE, | |
357 kGTE, | |
358 }; | |
359 | |
360 struct InstanceCallDescriptor { | |
361 // Standard (i.e. most non-Smi) functions. | |
362 explicit InstanceCallDescriptor(const String& name) | |
363 : name(name), | |
364 token_kind(Token::kILLEGAL), | |
365 checked_argument_count(1) { } | |
366 | |
367 InstanceCallDescriptor(const String& name, | |
368 Token::Kind token_kind, | |
369 intptr_t checked_argument_count) | |
370 : name(name), | |
371 token_kind(token_kind), | |
372 checked_argument_count(checked_argument_count) { } | |
373 | |
374 // Special cases for Smi and indexing functions. | |
375 static InstanceCallDescriptor FromToken(Token::Kind token_kind) { | |
376 switch (token_kind) { | |
377 case Token::kEQ: return InstanceCallDescriptor( | |
378 Symbols::EqualOperator(), token_kind, 2); | |
379 case Token::kADD: return InstanceCallDescriptor( | |
380 Symbols::Plus(), token_kind, 2); | |
381 case Token::kSUB: return InstanceCallDescriptor( | |
382 Symbols::Minus(), token_kind, 2); | |
383 case Token::kBIT_OR: return InstanceCallDescriptor( | |
384 Symbols::BitOr(), token_kind, 2); | |
385 case Token::kBIT_AND: return InstanceCallDescriptor( | |
386 Symbols::BitAnd(), token_kind, 2); | |
387 case Token::kLT: return InstanceCallDescriptor( | |
388 Symbols::LAngleBracket(), token_kind, 2); | |
389 case Token::kLTE: return InstanceCallDescriptor( | |
390 Symbols::LessEqualOperator(), token_kind, 2); | |
391 case Token::kGT: return InstanceCallDescriptor( | |
392 Symbols::RAngleBracket(), token_kind, 2); | |
393 case Token::kGTE: return InstanceCallDescriptor( | |
394 Symbols::GreaterEqualOperator(), token_kind, 2); | |
395 case Token::kNEGATE: return InstanceCallDescriptor( | |
396 Symbols::UnaryMinus(), token_kind, 1); | |
397 case Token::kINDEX: return InstanceCallDescriptor( | |
398 Symbols::IndexToken(), token_kind, 2); | |
399 case Token::kASSIGN_INDEX: return InstanceCallDescriptor( | |
400 Symbols::AssignIndexToken(), token_kind, 3); | |
401 default: | |
402 UNREACHABLE(); | |
403 } | |
404 UNREACHABLE(); | |
405 return InstanceCallDescriptor(Symbols::Empty()); | |
406 } | |
407 | |
408 const String& name; | |
409 Token::Kind token_kind; | |
410 intptr_t checked_argument_count; | |
411 }; | |
412 | |
413 LocalVariable* Local(const String& name); | |
414 LocalVariable* Parameter(const String& name, intptr_t index) const; | |
415 | |
416 ConstantInstr* Int64Constant(int64_t value) const; | |
417 ConstantInstr* Uint64Constant(uint64_t value) const; | |
418 ConstantInstr* BoolConstant(bool value) const; | |
419 ConstantInstr* StringConstant(const char* value) const; | |
420 | |
421 // The word character map static member of the RegExp class. | |
422 // Byte map of one byte characters with a 0xff if the character is a word | |
423 // character (digit, letter or underscore) and 0x00 otherwise. | |
424 // Used by generated RegExp code. | |
425 ConstantInstr* WordCharacterMapConstant() const; | |
426 | |
427 ComparisonInstr* Comparison(ComparisonKind kind, | |
428 Definition* lhs, Definition* rhs); | |
429 | |
430 InstanceCallInstr* InstanceCall(const InstanceCallDescriptor& desc, | |
431 PushArgumentInstr* arg1) const; | |
432 InstanceCallInstr* InstanceCall(const InstanceCallDescriptor& desc, | |
433 PushArgumentInstr* arg1, | |
434 PushArgumentInstr* arg2) const; | |
435 InstanceCallInstr* InstanceCall(const InstanceCallDescriptor& desc, | |
436 PushArgumentInstr* arg1, | |
437 PushArgumentInstr* arg2, | |
438 PushArgumentInstr* arg3) const; | |
439 InstanceCallInstr* InstanceCall( | |
440 const InstanceCallDescriptor& desc, | |
441 ZoneGrowableArray<PushArgumentInstr*>* arguments) const; | |
442 | |
443 StaticCallInstr* StaticCall(const Function& function) const; | |
444 StaticCallInstr* StaticCall(const Function& function, | |
445 PushArgumentInstr* arg1) const; | |
446 StaticCallInstr* StaticCall(const Function& function, | |
447 PushArgumentInstr* arg1, | |
448 PushArgumentInstr* arg2) const; | |
449 StaticCallInstr* StaticCall( | |
450 const Function& function, | |
451 ZoneGrowableArray<PushArgumentInstr*>* arguments) const; | |
452 | |
453 // Creates a new block consisting simply of a goto to dst. | |
454 TargetEntryInstr* TargetWithJoinGoto(JoinEntryInstr* dst); | |
455 IndirectEntryInstr* IndirectWithJoinGoto(JoinEntryInstr* dst); | |
456 | |
457 // Adds, respectively subtracts lhs and rhs and returns the result. | |
458 Value* Add(PushArgumentInstr* lhs, PushArgumentInstr* rhs); | |
459 Value* Sub(PushArgumentInstr* lhs, PushArgumentInstr* rhs); | |
460 | |
461 LoadLocalInstr* LoadLocal(LocalVariable* local) const; | |
462 void StoreLocal(LocalVariable* local, Value* value); | |
463 | |
464 PushArgumentInstr* PushArgument(Value* value); | |
465 PushArgumentInstr* PushLocal(LocalVariable* local); | |
466 | |
467 // Returns the character within the passed string at the specified index. | |
468 Value* CharacterAt(Definition* index); | |
469 | |
470 // Load a number of characters at the given offset from the | |
471 // current position, into the current-character register. | |
472 void LoadCurrentCharacterUnchecked(intptr_t cp_offset, | |
473 intptr_t character_count); | |
474 | |
475 // Check whether preemption has been requested. | |
476 void CheckPreemption(); | |
477 | |
478 // Byte size of chars in the string to match (decided by the Mode argument) | |
479 inline intptr_t char_size() { return static_cast<int>(mode_); } | |
480 | |
481 // Equivalent to a conditional branch to the label, unless the label | |
482 // is NULL, in which case it is a conditional Backtrack. | |
483 void BranchOrBacktrack(ComparisonInstr* comparison, | |
484 BlockLabel* true_successor); | |
485 | |
486 // Set up all local variables and parameters. | |
487 void InitializeLocals(); | |
488 | |
489 // Allocates a new local, and returns the appropriate id for placing it | |
490 // on the stack. | |
491 intptr_t GetNextLocalIndex(); | |
492 | |
493 // We never have any copied parameters. | |
494 intptr_t num_copied_params() const { | |
495 return 0; | |
496 } | |
497 | |
498 // Return the position register at the specified index, creating it if | |
499 // necessary. Note that the number of such registers can exceed the amount | |
500 // required by the number of output captures. | |
501 LocalVariable* position_register(intptr_t index); | |
502 | |
503 void set_current_instruction(Instruction* instruction); | |
504 | |
505 // The following functions are responsible for appending instructions | |
506 // to the current instruction in various ways. The most simple one | |
507 // is AppendInstruction, which simply appends an instruction and performs | |
508 // bookkeeping. | |
509 void AppendInstruction(Instruction* instruction); | |
510 // Similar to AppendInstruction, but closes the current block by | |
511 // setting current_instruction_ to NULL. | |
512 void CloseBlockWith(Instruction* instruction); | |
513 // Appends definition and allocates a temp index for the result. | |
514 Value* Bind(Definition* definition); | |
515 // Appends the definition. | |
516 void Do(Definition* definition); | |
517 // Closes the current block with a jump to the specified block. | |
518 void GoTo(JoinEntryInstr* to); | |
519 | |
520 // Accessors for our local stack_. | |
521 void PushStack(Definition* definition); | |
522 Value* PopStack(); | |
523 | |
524 // Prints the specified argument. Used for debugging. | |
525 void Print(PushArgumentInstr* argument); | |
526 | |
527 // A utility class tracking ids of various objects such as blocks, temps, etc. | |
528 class IdAllocator : public ValueObject { | |
529 public: | |
530 IdAllocator() : next_id(0) { } | |
531 | |
532 intptr_t Count() const { return next_id; } | |
533 intptr_t Alloc(intptr_t count = 1) { | |
534 ASSERT(count >= 0); | |
535 intptr_t current_id = next_id; | |
536 next_id += count; | |
537 return current_id; | |
538 } | |
539 void Dealloc(intptr_t count = 1) { | |
540 ASSERT(count <= next_id); | |
541 next_id -= count; | |
542 } | |
543 | |
544 private: | |
545 intptr_t next_id; | |
546 }; | |
547 | |
548 // Which mode to generate code for (ASCII or UC16). | |
549 Mode mode_; | |
550 | |
551 // Which specific string class to generate code for. | |
552 intptr_t specialization_cid_; | |
553 | |
554 // Block entries used internally. | |
555 GraphEntryInstr* entry_block_; | |
556 JoinEntryInstr* start_block_; | |
557 JoinEntryInstr* success_block_; | |
558 JoinEntryInstr* backtrack_block_; | |
559 JoinEntryInstr* exit_block_; | |
560 | |
561 const ParsedFunction* parsed_function_; | |
562 ZoneGrowableArray<const ICData*>* ic_data_array_; | |
563 | |
564 // All created blocks are contained within this set. Used for printing | |
565 // the generated code. | |
566 GrowableArray<BlockEntryInstr*> blocks_; | |
567 | |
568 // The current instruction to link to when new code is emitted. | |
569 Instruction* current_instruction_; | |
570 | |
571 // A list, acting as the runtime stack for both backtrack locations and | |
572 // stored positions within the string. | |
573 LocalVariable* stack_; | |
574 | |
575 // Stores the current character within the string. | |
576 LocalVariable* current_character_; | |
577 | |
578 // Stores the current location within the string as a negative offset | |
579 // from the end of the string. | |
580 LocalVariable* current_position_; | |
581 | |
582 // The string being processed, passed as a function parameter. | |
583 LocalVariable* string_param_; | |
584 | |
585 // Stores the length of string_param_. | |
586 LocalVariable* string_param_length_; | |
587 | |
588 // The start index within the string, passed as a function parameter. | |
589 LocalVariable* start_index_param_; | |
590 | |
591 // An assortment of utility variables. | |
592 LocalVariable* capture_length_; | |
593 LocalVariable* match_start_index_; | |
594 LocalVariable* capture_start_index_; | |
595 LocalVariable* match_end_index_; | |
596 LocalVariable* char_in_capture_; | |
597 LocalVariable* char_in_match_; | |
598 | |
599 LocalVariable* result_; | |
600 | |
601 // Stored positions containing group bounds. Generated as needed. | |
602 const intptr_t position_registers_count_; | |
603 GrowableArray<LocalVariable*> position_registers_; | |
604 | |
605 // The actual array object used as the stack. | |
606 GrowableObjectArray& stack_array_; | |
607 | |
608 GrowableArray<IndirectGotoInstr*> igotos_; | |
609 | |
610 IdAllocator block_id; | |
Florian Schneider
2014/10/07 12:49:37
Rename private members to have _ at the end
block
jgruber1
2014/10/07 15:00:25
Done.
| |
611 IdAllocator temp_id; | |
612 IdAllocator arg_id; | |
613 IdAllocator local_id; | |
614 IdAllocator indirect_id; | |
615 }; | |
616 | |
617 } // namespace dart | |
618 | |
619 #endif // VM_REGEXP_ASSEMBLER_H_ | |
OLD | NEW |