OLD | NEW |
| (Empty) |
1 // Copyright 2008-2009 the V8 project authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "src/v8.h" | |
6 | |
7 #include "src/ast.h" | |
8 #include "src/bytecodes-irregexp.h" | |
9 #include "src/regexp-macro-assembler.h" | |
10 #include "src/regexp-macro-assembler-irregexp.h" | |
11 #include "src/regexp-macro-assembler-irregexp-inl.h" | |
12 | |
13 | |
14 namespace v8 { | |
15 namespace internal { | |
16 | |
17 #ifdef V8_INTERPRETED_REGEXP | |
18 | |
19 RegExpMacroAssemblerIrregexp::RegExpMacroAssemblerIrregexp(Isolate* isolate, | |
20 Vector<byte> buffer, | |
21 Zone* zone) | |
22 : RegExpMacroAssembler(isolate, zone), | |
23 buffer_(buffer), | |
24 pc_(0), | |
25 own_buffer_(false), | |
26 advance_current_end_(kInvalidPC), | |
27 isolate_(isolate) {} | |
28 | |
29 | |
30 RegExpMacroAssemblerIrregexp::~RegExpMacroAssemblerIrregexp() { | |
31 if (backtrack_.is_linked()) backtrack_.Unuse(); | |
32 if (own_buffer_) buffer_.Dispose(); | |
33 } | |
34 | |
35 | |
36 RegExpMacroAssemblerIrregexp::IrregexpImplementation | |
37 RegExpMacroAssemblerIrregexp::Implementation() { | |
38 return kBytecodeImplementation; | |
39 } | |
40 | |
41 | |
42 void RegExpMacroAssemblerIrregexp::Bind(Label* l) { | |
43 advance_current_end_ = kInvalidPC; | |
44 DCHECK(!l->is_bound()); | |
45 if (l->is_linked()) { | |
46 int pos = l->pos(); | |
47 while (pos != 0) { | |
48 int fixup = pos; | |
49 pos = *reinterpret_cast<int32_t*>(buffer_.start() + fixup); | |
50 *reinterpret_cast<uint32_t*>(buffer_.start() + fixup) = pc_; | |
51 } | |
52 } | |
53 l->bind_to(pc_); | |
54 } | |
55 | |
56 | |
57 void RegExpMacroAssemblerIrregexp::EmitOrLink(Label* l) { | |
58 if (l == NULL) l = &backtrack_; | |
59 if (l->is_bound()) { | |
60 Emit32(l->pos()); | |
61 } else { | |
62 int pos = 0; | |
63 if (l->is_linked()) { | |
64 pos = l->pos(); | |
65 } | |
66 l->link_to(pc_); | |
67 Emit32(pos); | |
68 } | |
69 } | |
70 | |
71 | |
72 void RegExpMacroAssemblerIrregexp::PopRegister(int register_index) { | |
73 DCHECK(register_index >= 0); | |
74 DCHECK(register_index <= kMaxRegister); | |
75 Emit(BC_POP_REGISTER, register_index); | |
76 } | |
77 | |
78 | |
79 void RegExpMacroAssemblerIrregexp::PushRegister( | |
80 int register_index, | |
81 StackCheckFlag check_stack_limit) { | |
82 DCHECK(register_index >= 0); | |
83 DCHECK(register_index <= kMaxRegister); | |
84 Emit(BC_PUSH_REGISTER, register_index); | |
85 } | |
86 | |
87 | |
88 void RegExpMacroAssemblerIrregexp::WriteCurrentPositionToRegister( | |
89 int register_index, int cp_offset) { | |
90 DCHECK(register_index >= 0); | |
91 DCHECK(register_index <= kMaxRegister); | |
92 Emit(BC_SET_REGISTER_TO_CP, register_index); | |
93 Emit32(cp_offset); // Current position offset. | |
94 } | |
95 | |
96 | |
97 void RegExpMacroAssemblerIrregexp::ClearRegisters(int reg_from, int reg_to) { | |
98 DCHECK(reg_from <= reg_to); | |
99 for (int reg = reg_from; reg <= reg_to; reg++) { | |
100 SetRegister(reg, -1); | |
101 } | |
102 } | |
103 | |
104 | |
105 void RegExpMacroAssemblerIrregexp::ReadCurrentPositionFromRegister( | |
106 int register_index) { | |
107 DCHECK(register_index >= 0); | |
108 DCHECK(register_index <= kMaxRegister); | |
109 Emit(BC_SET_CP_TO_REGISTER, register_index); | |
110 } | |
111 | |
112 | |
113 void RegExpMacroAssemblerIrregexp::WriteStackPointerToRegister( | |
114 int register_index) { | |
115 DCHECK(register_index >= 0); | |
116 DCHECK(register_index <= kMaxRegister); | |
117 Emit(BC_SET_REGISTER_TO_SP, register_index); | |
118 } | |
119 | |
120 | |
121 void RegExpMacroAssemblerIrregexp::ReadStackPointerFromRegister( | |
122 int register_index) { | |
123 DCHECK(register_index >= 0); | |
124 DCHECK(register_index <= kMaxRegister); | |
125 Emit(BC_SET_SP_TO_REGISTER, register_index); | |
126 } | |
127 | |
128 | |
129 void RegExpMacroAssemblerIrregexp::SetCurrentPositionFromEnd(int by) { | |
130 DCHECK(is_uint24(by)); | |
131 Emit(BC_SET_CURRENT_POSITION_FROM_END, by); | |
132 } | |
133 | |
134 | |
135 void RegExpMacroAssemblerIrregexp::SetRegister(int register_index, int to) { | |
136 DCHECK(register_index >= 0); | |
137 DCHECK(register_index <= kMaxRegister); | |
138 Emit(BC_SET_REGISTER, register_index); | |
139 Emit32(to); | |
140 } | |
141 | |
142 | |
143 void RegExpMacroAssemblerIrregexp::AdvanceRegister(int register_index, int by) { | |
144 DCHECK(register_index >= 0); | |
145 DCHECK(register_index <= kMaxRegister); | |
146 Emit(BC_ADVANCE_REGISTER, register_index); | |
147 Emit32(by); | |
148 } | |
149 | |
150 | |
151 void RegExpMacroAssemblerIrregexp::PopCurrentPosition() { | |
152 Emit(BC_POP_CP, 0); | |
153 } | |
154 | |
155 | |
156 void RegExpMacroAssemblerIrregexp::PushCurrentPosition() { | |
157 Emit(BC_PUSH_CP, 0); | |
158 } | |
159 | |
160 | |
161 void RegExpMacroAssemblerIrregexp::Backtrack() { | |
162 Emit(BC_POP_BT, 0); | |
163 } | |
164 | |
165 | |
166 void RegExpMacroAssemblerIrregexp::GoTo(Label* l) { | |
167 if (advance_current_end_ == pc_) { | |
168 // Combine advance current and goto. | |
169 pc_ = advance_current_start_; | |
170 Emit(BC_ADVANCE_CP_AND_GOTO, advance_current_offset_); | |
171 EmitOrLink(l); | |
172 advance_current_end_ = kInvalidPC; | |
173 } else { | |
174 // Regular goto. | |
175 Emit(BC_GOTO, 0); | |
176 EmitOrLink(l); | |
177 } | |
178 } | |
179 | |
180 | |
181 void RegExpMacroAssemblerIrregexp::PushBacktrack(Label* l) { | |
182 Emit(BC_PUSH_BT, 0); | |
183 EmitOrLink(l); | |
184 } | |
185 | |
186 | |
187 bool RegExpMacroAssemblerIrregexp::Succeed() { | |
188 Emit(BC_SUCCEED, 0); | |
189 return false; // Restart matching for global regexp not supported. | |
190 } | |
191 | |
192 | |
193 void RegExpMacroAssemblerIrregexp::Fail() { | |
194 Emit(BC_FAIL, 0); | |
195 } | |
196 | |
197 | |
198 void RegExpMacroAssemblerIrregexp::AdvanceCurrentPosition(int by) { | |
199 DCHECK(by >= kMinCPOffset); | |
200 DCHECK(by <= kMaxCPOffset); | |
201 advance_current_start_ = pc_; | |
202 advance_current_offset_ = by; | |
203 Emit(BC_ADVANCE_CP, by); | |
204 advance_current_end_ = pc_; | |
205 } | |
206 | |
207 | |
208 void RegExpMacroAssemblerIrregexp::CheckGreedyLoop( | |
209 Label* on_tos_equals_current_position) { | |
210 Emit(BC_CHECK_GREEDY, 0); | |
211 EmitOrLink(on_tos_equals_current_position); | |
212 } | |
213 | |
214 | |
215 void RegExpMacroAssemblerIrregexp::LoadCurrentCharacter(int cp_offset, | |
216 Label* on_failure, | |
217 bool check_bounds, | |
218 int characters) { | |
219 DCHECK(cp_offset >= kMinCPOffset); | |
220 DCHECK(cp_offset <= kMaxCPOffset); | |
221 int bytecode; | |
222 if (check_bounds) { | |
223 if (characters == 4) { | |
224 bytecode = BC_LOAD_4_CURRENT_CHARS; | |
225 } else if (characters == 2) { | |
226 bytecode = BC_LOAD_2_CURRENT_CHARS; | |
227 } else { | |
228 DCHECK(characters == 1); | |
229 bytecode = BC_LOAD_CURRENT_CHAR; | |
230 } | |
231 } else { | |
232 if (characters == 4) { | |
233 bytecode = BC_LOAD_4_CURRENT_CHARS_UNCHECKED; | |
234 } else if (characters == 2) { | |
235 bytecode = BC_LOAD_2_CURRENT_CHARS_UNCHECKED; | |
236 } else { | |
237 DCHECK(characters == 1); | |
238 bytecode = BC_LOAD_CURRENT_CHAR_UNCHECKED; | |
239 } | |
240 } | |
241 Emit(bytecode, cp_offset); | |
242 if (check_bounds) EmitOrLink(on_failure); | |
243 } | |
244 | |
245 | |
246 void RegExpMacroAssemblerIrregexp::CheckCharacterLT(uc16 limit, | |
247 Label* on_less) { | |
248 Emit(BC_CHECK_LT, limit); | |
249 EmitOrLink(on_less); | |
250 } | |
251 | |
252 | |
253 void RegExpMacroAssemblerIrregexp::CheckCharacterGT(uc16 limit, | |
254 Label* on_greater) { | |
255 Emit(BC_CHECK_GT, limit); | |
256 EmitOrLink(on_greater); | |
257 } | |
258 | |
259 | |
260 void RegExpMacroAssemblerIrregexp::CheckCharacter(uint32_t c, Label* on_equal) { | |
261 if (c > MAX_FIRST_ARG) { | |
262 Emit(BC_CHECK_4_CHARS, 0); | |
263 Emit32(c); | |
264 } else { | |
265 Emit(BC_CHECK_CHAR, c); | |
266 } | |
267 EmitOrLink(on_equal); | |
268 } | |
269 | |
270 | |
271 void RegExpMacroAssemblerIrregexp::CheckAtStart(Label* on_at_start) { | |
272 Emit(BC_CHECK_AT_START, 0); | |
273 EmitOrLink(on_at_start); | |
274 } | |
275 | |
276 | |
277 void RegExpMacroAssemblerIrregexp::CheckNotAtStart(Label* on_not_at_start) { | |
278 Emit(BC_CHECK_NOT_AT_START, 0); | |
279 EmitOrLink(on_not_at_start); | |
280 } | |
281 | |
282 | |
283 void RegExpMacroAssemblerIrregexp::CheckNotCharacter(uint32_t c, | |
284 Label* on_not_equal) { | |
285 if (c > MAX_FIRST_ARG) { | |
286 Emit(BC_CHECK_NOT_4_CHARS, 0); | |
287 Emit32(c); | |
288 } else { | |
289 Emit(BC_CHECK_NOT_CHAR, c); | |
290 } | |
291 EmitOrLink(on_not_equal); | |
292 } | |
293 | |
294 | |
295 void RegExpMacroAssemblerIrregexp::CheckCharacterAfterAnd( | |
296 uint32_t c, | |
297 uint32_t mask, | |
298 Label* on_equal) { | |
299 if (c > MAX_FIRST_ARG) { | |
300 Emit(BC_AND_CHECK_4_CHARS, 0); | |
301 Emit32(c); | |
302 } else { | |
303 Emit(BC_AND_CHECK_CHAR, c); | |
304 } | |
305 Emit32(mask); | |
306 EmitOrLink(on_equal); | |
307 } | |
308 | |
309 | |
310 void RegExpMacroAssemblerIrregexp::CheckNotCharacterAfterAnd( | |
311 uint32_t c, | |
312 uint32_t mask, | |
313 Label* on_not_equal) { | |
314 if (c > MAX_FIRST_ARG) { | |
315 Emit(BC_AND_CHECK_NOT_4_CHARS, 0); | |
316 Emit32(c); | |
317 } else { | |
318 Emit(BC_AND_CHECK_NOT_CHAR, c); | |
319 } | |
320 Emit32(mask); | |
321 EmitOrLink(on_not_equal); | |
322 } | |
323 | |
324 | |
325 void RegExpMacroAssemblerIrregexp::CheckNotCharacterAfterMinusAnd( | |
326 uc16 c, | |
327 uc16 minus, | |
328 uc16 mask, | |
329 Label* on_not_equal) { | |
330 Emit(BC_MINUS_AND_CHECK_NOT_CHAR, c); | |
331 Emit16(minus); | |
332 Emit16(mask); | |
333 EmitOrLink(on_not_equal); | |
334 } | |
335 | |
336 | |
337 void RegExpMacroAssemblerIrregexp::CheckCharacterInRange( | |
338 uc16 from, | |
339 uc16 to, | |
340 Label* on_in_range) { | |
341 Emit(BC_CHECK_CHAR_IN_RANGE, 0); | |
342 Emit16(from); | |
343 Emit16(to); | |
344 EmitOrLink(on_in_range); | |
345 } | |
346 | |
347 | |
348 void RegExpMacroAssemblerIrregexp::CheckCharacterNotInRange( | |
349 uc16 from, | |
350 uc16 to, | |
351 Label* on_not_in_range) { | |
352 Emit(BC_CHECK_CHAR_NOT_IN_RANGE, 0); | |
353 Emit16(from); | |
354 Emit16(to); | |
355 EmitOrLink(on_not_in_range); | |
356 } | |
357 | |
358 | |
359 void RegExpMacroAssemblerIrregexp::CheckBitInTable( | |
360 Handle<ByteArray> table, Label* on_bit_set) { | |
361 Emit(BC_CHECK_BIT_IN_TABLE, 0); | |
362 EmitOrLink(on_bit_set); | |
363 for (int i = 0; i < kTableSize; i += kBitsPerByte) { | |
364 int byte = 0; | |
365 for (int j = 0; j < kBitsPerByte; j++) { | |
366 if (table->get(i + j) != 0) byte |= 1 << j; | |
367 } | |
368 Emit8(byte); | |
369 } | |
370 } | |
371 | |
372 | |
373 void RegExpMacroAssemblerIrregexp::CheckNotBackReference(int start_reg, | |
374 Label* on_not_equal) { | |
375 DCHECK(start_reg >= 0); | |
376 DCHECK(start_reg <= kMaxRegister); | |
377 Emit(BC_CHECK_NOT_BACK_REF, start_reg); | |
378 EmitOrLink(on_not_equal); | |
379 } | |
380 | |
381 | |
382 void RegExpMacroAssemblerIrregexp::CheckNotBackReferenceIgnoreCase( | |
383 int start_reg, | |
384 Label* on_not_equal) { | |
385 DCHECK(start_reg >= 0); | |
386 DCHECK(start_reg <= kMaxRegister); | |
387 Emit(BC_CHECK_NOT_BACK_REF_NO_CASE, start_reg); | |
388 EmitOrLink(on_not_equal); | |
389 } | |
390 | |
391 | |
392 void RegExpMacroAssemblerIrregexp::IfRegisterLT(int register_index, | |
393 int comparand, | |
394 Label* on_less_than) { | |
395 DCHECK(register_index >= 0); | |
396 DCHECK(register_index <= kMaxRegister); | |
397 Emit(BC_CHECK_REGISTER_LT, register_index); | |
398 Emit32(comparand); | |
399 EmitOrLink(on_less_than); | |
400 } | |
401 | |
402 | |
403 void RegExpMacroAssemblerIrregexp::IfRegisterGE(int register_index, | |
404 int comparand, | |
405 Label* on_greater_or_equal) { | |
406 DCHECK(register_index >= 0); | |
407 DCHECK(register_index <= kMaxRegister); | |
408 Emit(BC_CHECK_REGISTER_GE, register_index); | |
409 Emit32(comparand); | |
410 EmitOrLink(on_greater_or_equal); | |
411 } | |
412 | |
413 | |
414 void RegExpMacroAssemblerIrregexp::IfRegisterEqPos(int register_index, | |
415 Label* on_eq) { | |
416 DCHECK(register_index >= 0); | |
417 DCHECK(register_index <= kMaxRegister); | |
418 Emit(BC_CHECK_REGISTER_EQ_POS, register_index); | |
419 EmitOrLink(on_eq); | |
420 } | |
421 | |
422 | |
423 Handle<HeapObject> RegExpMacroAssemblerIrregexp::GetCode( | |
424 Handle<String> source) { | |
425 Bind(&backtrack_); | |
426 Emit(BC_POP_BT, 0); | |
427 Handle<ByteArray> array = isolate_->factory()->NewByteArray(length()); | |
428 Copy(array->GetDataStartAddress()); | |
429 return array; | |
430 } | |
431 | |
432 | |
433 int RegExpMacroAssemblerIrregexp::length() { | |
434 return pc_; | |
435 } | |
436 | |
437 | |
438 void RegExpMacroAssemblerIrregexp::Copy(Address a) { | |
439 MemCopy(a, buffer_.start(), length()); | |
440 } | |
441 | |
442 | |
443 void RegExpMacroAssemblerIrregexp::Expand() { | |
444 bool old_buffer_was_our_own = own_buffer_; | |
445 Vector<byte> old_buffer = buffer_; | |
446 buffer_ = Vector<byte>::New(old_buffer.length() * 2); | |
447 own_buffer_ = true; | |
448 MemCopy(buffer_.start(), old_buffer.start(), old_buffer.length()); | |
449 if (old_buffer_was_our_own) { | |
450 old_buffer.Dispose(); | |
451 } | |
452 } | |
453 | |
454 #endif // V8_INTERPRETED_REGEXP | |
455 | |
456 } // namespace internal | |
457 } // namespace v8 | |
OLD | NEW |