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 #include "vm/regexp.h" | 5 #include "vm/regexp.h" |
6 | 6 |
7 #include "vm/dart_entry.h" | 7 #include "vm/dart_entry.h" |
8 #include "vm/regexp_assembler.h" | 8 #include "vm/regexp_assembler.h" |
| 9 #include "vm/regexp_assembler_bytecode.h" |
| 10 #include "vm/regexp_assembler_ir.h" |
9 #include "vm/regexp_ast.h" | 11 #include "vm/regexp_ast.h" |
10 #include "vm/unibrow-inl.h" | 12 #include "vm/unibrow-inl.h" |
11 #include "vm/unicode.h" | 13 #include "vm/unicode.h" |
12 #include "vm/symbols.h" | 14 #include "vm/symbols.h" |
13 #include "vm/thread.h" | 15 #include "vm/thread.h" |
14 | 16 |
15 #define Z (zone()) | 17 #define Z (zone()) |
16 | 18 |
17 namespace dart { | 19 namespace dart { |
18 | 20 |
19 DECLARE_FLAG(bool, trace_irregexp); | 21 DECLARE_FLAG(bool, trace_irregexp); |
| 22 DEFINE_FLAG(bool, interpret_irregexp, false, |
| 23 "Use irregexp bytecode interpreter"); |
20 | 24 |
21 // Default to generating optimized regexp code. | 25 // Default to generating optimized regexp code. |
22 static const bool kRegexpOptimization = true; | 26 static const bool kRegexpOptimization = true; |
23 | 27 |
24 // More makes code generation slower, less makes V8 benchmark score lower. | 28 // More makes code generation slower, less makes V8 benchmark score lower. |
25 static const intptr_t kMaxLookaheadForBoyerMoore = 8; | 29 static const intptr_t kMaxLookaheadForBoyerMoore = 8; |
26 | 30 |
27 ContainedInLattice AddRange(ContainedInLattice containment, | 31 ContainedInLattice AddRange(ContainedInLattice containment, |
28 const intptr_t* ranges, | 32 const intptr_t* ranges, |
29 intptr_t ranges_length, | 33 intptr_t ranges_length, |
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
287 private: | 291 private: |
288 CharacterFrequency frequencies_[RegExpMacroAssembler::kTableSize]; | 292 CharacterFrequency frequencies_[RegExpMacroAssembler::kTableSize]; |
289 intptr_t total_samples_; | 293 intptr_t total_samples_; |
290 }; | 294 }; |
291 | 295 |
292 | 296 |
293 class RegExpCompiler : public ValueObject { | 297 class RegExpCompiler : public ValueObject { |
294 public: | 298 public: |
295 RegExpCompiler(intptr_t capture_count, | 299 RegExpCompiler(intptr_t capture_count, |
296 bool ignore_case, | 300 bool ignore_case, |
297 intptr_t specialization_cid); | 301 bool is_one_byte); |
298 | 302 |
299 intptr_t AllocateRegister() { | 303 intptr_t AllocateRegister() { |
300 return next_register_++; | 304 return next_register_++; |
301 } | 305 } |
302 | 306 |
303 RegExpEngine::CompilationResult Assemble(IRRegExpMacroAssembler* assembler, | 307 RegExpEngine::CompilationResult Assemble( |
304 RegExpNode* start, | 308 IRRegExpMacroAssembler* assembler, |
305 intptr_t capture_count, | 309 RegExpNode* start, |
306 const String& pattern); | 310 intptr_t capture_count, |
| 311 const String& pattern); |
| 312 |
| 313 RegExpEngine::CompilationResult Assemble( |
| 314 BytecodeRegExpMacroAssembler* assembler, |
| 315 RegExpNode* start, |
| 316 intptr_t capture_count, |
| 317 const String& pattern); |
307 | 318 |
308 inline void AddWork(RegExpNode* node) { work_list_->Add(node); } | 319 inline void AddWork(RegExpNode* node) { work_list_->Add(node); } |
309 | 320 |
310 static const intptr_t kImplementationOffset = 0; | 321 static const intptr_t kImplementationOffset = 0; |
311 static const intptr_t kNumberOfRegistersOffset = 0; | 322 static const intptr_t kNumberOfRegistersOffset = 0; |
312 static const intptr_t kCodeOffset = 1; | 323 static const intptr_t kCodeOffset = 1; |
313 | 324 |
314 IRRegExpMacroAssembler* macro_assembler() { return macro_assembler_; } | 325 RegExpMacroAssembler* macro_assembler() { return macro_assembler_; } |
315 EndNode* accept() { return accept_; } | 326 EndNode* accept() { return accept_; } |
316 | 327 |
317 static const intptr_t kMaxRecursion = 100; | 328 static const intptr_t kMaxRecursion = 100; |
318 inline intptr_t recursion_depth() { return recursion_depth_; } | 329 inline intptr_t recursion_depth() { return recursion_depth_; } |
319 inline void IncrementRecursionDepth() { recursion_depth_++; } | 330 inline void IncrementRecursionDepth() { recursion_depth_++; } |
320 inline void DecrementRecursionDepth() { recursion_depth_--; } | 331 inline void DecrementRecursionDepth() { recursion_depth_--; } |
321 | 332 |
322 void SetRegExpTooBig() { reg_exp_too_big_ = true; } | 333 void SetRegExpTooBig() { reg_exp_too_big_ = true; } |
323 | 334 |
324 inline bool ignore_case() { return ignore_case_; } | 335 inline bool ignore_case() { return ignore_case_; } |
325 inline bool one_byte() const { | 336 inline bool one_byte() const { return is_one_byte_; } |
326 return (specialization_cid_ == kOneByteStringCid || | |
327 specialization_cid_ == kExternalOneByteStringCid); | |
328 } | |
329 inline intptr_t specialization_cid() { return specialization_cid_; } | |
330 FrequencyCollator* frequency_collator() { return &frequency_collator_; } | 337 FrequencyCollator* frequency_collator() { return &frequency_collator_; } |
331 | 338 |
332 intptr_t current_expansion_factor() { return current_expansion_factor_; } | 339 intptr_t current_expansion_factor() { return current_expansion_factor_; } |
333 void set_current_expansion_factor(intptr_t value) { | 340 void set_current_expansion_factor(intptr_t value) { |
334 current_expansion_factor_ = value; | 341 current_expansion_factor_ = value; |
335 } | 342 } |
336 | 343 |
337 Zone* zone() const { return zone_; } | 344 Zone* zone() const { return zone_; } |
338 | 345 |
339 static const intptr_t kNoRegister = -1; | 346 static const intptr_t kNoRegister = -1; |
340 | 347 |
341 private: | 348 private: |
342 EndNode* accept_; | 349 EndNode* accept_; |
343 intptr_t next_register_; | 350 intptr_t next_register_; |
344 ZoneGrowableArray<RegExpNode*>* work_list_; | 351 ZoneGrowableArray<RegExpNode*>* work_list_; |
345 intptr_t recursion_depth_; | 352 intptr_t recursion_depth_; |
346 IRRegExpMacroAssembler* macro_assembler_; | 353 RegExpMacroAssembler* macro_assembler_; |
347 bool ignore_case_; | 354 bool ignore_case_; |
348 intptr_t specialization_cid_; | 355 bool is_one_byte_; |
349 bool reg_exp_too_big_; | 356 bool reg_exp_too_big_; |
350 intptr_t current_expansion_factor_; | 357 intptr_t current_expansion_factor_; |
351 FrequencyCollator frequency_collator_; | 358 FrequencyCollator frequency_collator_; |
352 Zone* zone_; | 359 Zone* zone_; |
353 }; | 360 }; |
354 | 361 |
355 | 362 |
356 class RecursionCheck : public ValueObject { | 363 class RecursionCheck : public ValueObject { |
357 public: | 364 public: |
358 explicit RecursionCheck(RegExpCompiler* compiler) : compiler_(compiler) { | 365 explicit RecursionCheck(RegExpCompiler* compiler) : compiler_(compiler) { |
359 compiler->IncrementRecursionDepth(); | 366 compiler->IncrementRecursionDepth(); |
360 } | 367 } |
361 ~RecursionCheck() { compiler_->DecrementRecursionDepth(); } | 368 ~RecursionCheck() { compiler_->DecrementRecursionDepth(); } |
362 private: | 369 private: |
363 RegExpCompiler* compiler_; | 370 RegExpCompiler* compiler_; |
364 }; | 371 }; |
365 | 372 |
366 | 373 |
367 static RegExpEngine::CompilationResult IrregexpRegExpTooBig() { | 374 static RegExpEngine::CompilationResult IrregexpRegExpTooBig() { |
368 return RegExpEngine::CompilationResult("RegExp too big"); | 375 return RegExpEngine::CompilationResult("RegExp too big"); |
369 } | 376 } |
370 | 377 |
371 | 378 |
372 // Attempts to compile the regexp using an Irregexp code generator. Returns | 379 // Attempts to compile the regexp using an Irregexp code generator. Returns |
373 // a fixed array or a null handle depending on whether it succeeded. | 380 // a fixed array or a null handle depending on whether it succeeded. |
374 RegExpCompiler::RegExpCompiler(intptr_t capture_count, bool ignore_case, | 381 RegExpCompiler::RegExpCompiler(intptr_t capture_count, |
375 intptr_t specialization_cid) | 382 bool ignore_case, |
| 383 bool is_one_byte) |
376 : next_register_(2 * (capture_count + 1)), | 384 : next_register_(2 * (capture_count + 1)), |
377 work_list_(NULL), | 385 work_list_(NULL), |
378 recursion_depth_(0), | 386 recursion_depth_(0), |
379 ignore_case_(ignore_case), | 387 ignore_case_(ignore_case), |
380 specialization_cid_(specialization_cid), | 388 is_one_byte_(is_one_byte), |
381 reg_exp_too_big_(false), | 389 reg_exp_too_big_(false), |
382 current_expansion_factor_(1), | 390 current_expansion_factor_(1), |
383 zone_(Thread::Current()->zone()) { | 391 zone_(Thread::Current()->zone()) { |
384 accept_ = new(Z) EndNode(EndNode::ACCEPT, Z); | 392 accept_ = new(Z) EndNode(EndNode::ACCEPT, Z); |
385 } | 393 } |
386 | 394 |
387 | 395 |
388 RegExpEngine::CompilationResult RegExpCompiler::Assemble( | 396 RegExpEngine::CompilationResult RegExpCompiler::Assemble( |
389 IRRegExpMacroAssembler* macro_assembler, | 397 IRRegExpMacroAssembler* macro_assembler, |
390 RegExpNode* start, | 398 RegExpNode* start, |
391 intptr_t capture_count, | 399 intptr_t capture_count, |
392 const String& pattern) { | 400 const String& pattern) { |
393 static const bool use_slow_safe_regexp_compiler = false; | 401 macro_assembler->set_slow_safe(false /* use_slow_safe_regexp_compiler */); |
394 | |
395 macro_assembler->set_slow_safe(use_slow_safe_regexp_compiler); | |
396 macro_assembler_ = macro_assembler; | 402 macro_assembler_ = macro_assembler; |
397 | 403 |
398 ZoneGrowableArray<RegExpNode*> work_list(0); | 404 ZoneGrowableArray<RegExpNode*> work_list(0); |
399 work_list_ = &work_list; | 405 work_list_ = &work_list; |
400 BlockLabel fail; | 406 BlockLabel fail; |
401 macro_assembler_->PushBacktrack(&fail); | 407 macro_assembler_->PushBacktrack(&fail); |
402 Trace new_trace; | 408 Trace new_trace; |
403 start->Emit(this, &new_trace); | 409 start->Emit(this, &new_trace); |
404 macro_assembler_->BindBlock(&fail); | 410 macro_assembler_->BindBlock(&fail); |
405 macro_assembler_->Fail(); | 411 macro_assembler_->Fail(); |
406 while (!work_list.is_empty()) { | 412 while (!work_list.is_empty()) { |
407 work_list.RemoveLast()->Emit(this, &new_trace); | 413 work_list.RemoveLast()->Emit(this, &new_trace); |
408 } | 414 } |
409 if (reg_exp_too_big_) return IrregexpRegExpTooBig(); | 415 if (reg_exp_too_big_) return IrregexpRegExpTooBig(); |
410 | 416 |
411 macro_assembler->GenerateBacktrackBlock(); | 417 macro_assembler->GenerateBacktrackBlock(); |
412 macro_assembler->FinalizeRegistersArray(); | 418 macro_assembler->FinalizeRegistersArray(); |
413 | 419 |
414 return RegExpEngine::CompilationResult(macro_assembler->backtrack_goto(), | 420 return RegExpEngine::CompilationResult(macro_assembler->backtrack_goto(), |
415 macro_assembler->graph_entry(), | 421 macro_assembler->graph_entry(), |
416 macro_assembler->num_blocks(), | 422 macro_assembler->num_blocks(), |
417 macro_assembler->num_stack_locals()); | 423 macro_assembler->num_stack_locals(), |
| 424 next_register_); |
418 } | 425 } |
419 | 426 |
420 | 427 |
| 428 RegExpEngine::CompilationResult RegExpCompiler::Assemble( |
| 429 BytecodeRegExpMacroAssembler* macro_assembler, |
| 430 RegExpNode* start, |
| 431 intptr_t capture_count, |
| 432 const String& pattern) { |
| 433 macro_assembler->set_slow_safe(false /* use_slow_safe_regexp_compiler */); |
| 434 macro_assembler_ = macro_assembler; |
| 435 |
| 436 ZoneGrowableArray<RegExpNode*> work_list(0); |
| 437 work_list_ = &work_list; |
| 438 BlockLabel fail; |
| 439 macro_assembler_->PushBacktrack(&fail); |
| 440 Trace new_trace; |
| 441 start->Emit(this, &new_trace); |
| 442 macro_assembler_->BindBlock(&fail); |
| 443 macro_assembler_->Fail(); |
| 444 while (!work_list.is_empty()) { |
| 445 work_list.RemoveLast()->Emit(this, &new_trace); |
| 446 } |
| 447 if (reg_exp_too_big_) return IrregexpRegExpTooBig(); |
| 448 |
| 449 TypedData& bytecode = TypedData::ZoneHandle(macro_assembler->GetBytecode()); |
| 450 return RegExpEngine::CompilationResult(&bytecode, next_register_); |
| 451 } |
| 452 |
| 453 |
421 bool Trace::DeferredAction::Mentions(intptr_t that) { | 454 bool Trace::DeferredAction::Mentions(intptr_t that) { |
422 if (action_type() == ActionNode::CLEAR_CAPTURES) { | 455 if (action_type() == ActionNode::CLEAR_CAPTURES) { |
423 Interval range = static_cast<DeferredClearCaptures*>(this)->range(); | 456 Interval range = static_cast<DeferredClearCaptures*>(this)->range(); |
424 return range.Contains(that); | 457 return range.Contains(that); |
425 } else { | 458 } else { |
426 return reg() == that; | 459 return reg() == that; |
427 } | 460 } |
428 } | 461 } |
429 | 462 |
430 | 463 |
(...skipping 4538 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4969 return; | 5002 return; |
4970 } | 5003 } |
4971 on_success()->FillInBMInfo(offset, | 5004 on_success()->FillInBMInfo(offset, |
4972 budget - 1, | 5005 budget - 1, |
4973 bm, | 5006 bm, |
4974 true); // Not at start after a text node. | 5007 true); // Not at start after a text node. |
4975 if (initial_offset == 0) set_bm_info(not_at_start, bm); | 5008 if (initial_offset == 0) set_bm_info(not_at_start, bm); |
4976 } | 5009 } |
4977 | 5010 |
4978 | 5011 |
4979 RegExpEngine::CompilationResult RegExpEngine::Compile( | 5012 RegExpEngine::CompilationResult RegExpEngine::CompileIR( |
4980 RegExpCompileData* data, | 5013 RegExpCompileData* data, |
4981 const ParsedFunction* parsed_function, | 5014 const ParsedFunction* parsed_function, |
4982 const ZoneGrowableArray<const ICData*>& ic_data_array) { | 5015 const ZoneGrowableArray<const ICData*>& ic_data_array) { |
| 5016 ASSERT(!FLAG_interpret_irregexp); |
4983 Zone* zone = Thread::Current()->zone(); | 5017 Zone* zone = Thread::Current()->zone(); |
4984 | 5018 |
4985 const Function& function = parsed_function->function(); | 5019 const Function& function = parsed_function->function(); |
4986 const intptr_t specialization_cid = function.regexp_cid(); | 5020 const intptr_t specialization_cid = function.regexp_cid(); |
4987 const bool is_one_byte = (specialization_cid == kOneByteStringCid || | 5021 const bool is_one_byte = (specialization_cid == kOneByteStringCid || |
4988 specialization_cid == kExternalOneByteStringCid); | 5022 specialization_cid == kExternalOneByteStringCid); |
4989 JSRegExp& regexp = JSRegExp::Handle(zone, function.regexp()); | 5023 JSRegExp& regexp = JSRegExp::Handle(zone, function.regexp()); |
4990 const String& pattern = String::Handle(zone, regexp.pattern()); | 5024 const String& pattern = String::Handle(zone, regexp.pattern()); |
4991 | 5025 |
4992 ASSERT(!regexp.IsNull()); | 5026 ASSERT(!regexp.IsNull()); |
4993 ASSERT(!pattern.IsNull()); | 5027 ASSERT(!pattern.IsNull()); |
4994 | 5028 |
4995 const bool ignore_case = regexp.is_ignore_case(); | 5029 const bool ignore_case = regexp.is_ignore_case(); |
4996 const bool is_global = regexp.is_global(); | 5030 const bool is_global = regexp.is_global(); |
4997 | 5031 |
4998 RegExpCompiler compiler(data->capture_count, ignore_case, specialization_cid); | 5032 RegExpCompiler compiler(data->capture_count, ignore_case, is_one_byte); |
4999 | 5033 |
5000 // TODO(zerny): Frequency sampling is currently disabled because of several | 5034 // TODO(zerny): Frequency sampling is currently disabled because of several |
5001 // issues. We do not want to store subject strings in the regexp object since | 5035 // issues. We do not want to store subject strings in the regexp object since |
5002 // they might be long and we should not prevent their garbage collection. | 5036 // they might be long and we should not prevent their garbage collection. |
5003 // Passing them to this function explicitly does not help, since we must | 5037 // Passing them to this function explicitly does not help, since we must |
5004 // generate exactly the same IR for both the unoptimizing and optimizing | 5038 // generate exactly the same IR for both the unoptimizing and optimizing |
5005 // pipelines (otherwise it gets confused when i.e. deopt id's differ). | 5039 // pipelines (otherwise it gets confused when i.e. deopt id's differ). |
5006 // An option would be to store sampling results in the regexp object, but | 5040 // An option would be to store sampling results in the regexp object, but |
5007 // I'm not sure the performance gains are relevant enough. | 5041 // I'm not sure the performance gains are relevant enough. |
5008 | 5042 |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5091 pattern); | 5125 pattern); |
5092 | 5126 |
5093 if (FLAG_trace_irregexp) { | 5127 if (FLAG_trace_irregexp) { |
5094 macro_assembler->PrintBlocks(); | 5128 macro_assembler->PrintBlocks(); |
5095 } | 5129 } |
5096 | 5130 |
5097 return result; | 5131 return result; |
5098 } | 5132 } |
5099 | 5133 |
5100 | 5134 |
| 5135 RegExpEngine::CompilationResult RegExpEngine::CompileBytecode( |
| 5136 RegExpCompileData* data, |
| 5137 const JSRegExp& regexp, |
| 5138 bool is_one_byte, |
| 5139 Zone* zone) { |
| 5140 ASSERT(FLAG_interpret_irregexp); |
| 5141 const String& pattern = String::Handle(zone, regexp.pattern()); |
| 5142 |
| 5143 ASSERT(!regexp.IsNull()); |
| 5144 ASSERT(!pattern.IsNull()); |
| 5145 |
| 5146 const bool ignore_case = regexp.is_ignore_case(); |
| 5147 const bool is_global = regexp.is_global(); |
| 5148 |
| 5149 RegExpCompiler compiler(data->capture_count, ignore_case, is_one_byte); |
| 5150 |
| 5151 // TODO(zerny): Frequency sampling is currently disabled because of several |
| 5152 // issues. We do not want to store subject strings in the regexp object since |
| 5153 // they might be long and we should not prevent their garbage collection. |
| 5154 // Passing them to this function explicitly does not help, since we must |
| 5155 // generate exactly the same IR for both the unoptimizing and optimizing |
| 5156 // pipelines (otherwise it gets confused when i.e. deopt id's differ). |
| 5157 // An option would be to store sampling results in the regexp object, but |
| 5158 // I'm not sure the performance gains are relevant enough. |
| 5159 |
| 5160 // Wrap the body of the regexp in capture #0. |
| 5161 RegExpNode* captured_body = RegExpCapture::ToNode(data->tree, |
| 5162 0, |
| 5163 &compiler, |
| 5164 compiler.accept()); |
| 5165 |
| 5166 RegExpNode* node = captured_body; |
| 5167 bool is_end_anchored = data->tree->IsAnchoredAtEnd(); |
| 5168 bool is_start_anchored = data->tree->IsAnchoredAtStart(); |
| 5169 intptr_t max_length = data->tree->max_match(); |
| 5170 if (!is_start_anchored) { |
| 5171 // Add a .*? at the beginning, outside the body capture, unless |
| 5172 // this expression is anchored at the beginning. |
| 5173 RegExpNode* loop_node = |
| 5174 RegExpQuantifier::ToNode(0, |
| 5175 RegExpTree::kInfinity, |
| 5176 false, |
| 5177 new(zone) RegExpCharacterClass('*'), |
| 5178 &compiler, |
| 5179 captured_body, |
| 5180 data->contains_anchor); |
| 5181 |
| 5182 if (data->contains_anchor) { |
| 5183 // Unroll loop once, to take care of the case that might start |
| 5184 // at the start of input. |
| 5185 ChoiceNode* first_step_node = new(zone) ChoiceNode(2, zone); |
| 5186 first_step_node->AddAlternative(GuardedAlternative(captured_body)); |
| 5187 first_step_node->AddAlternative(GuardedAlternative( |
| 5188 new(zone) TextNode( |
| 5189 new(zone) RegExpCharacterClass('*'), loop_node))); |
| 5190 node = first_step_node; |
| 5191 } else { |
| 5192 node = loop_node; |
| 5193 } |
| 5194 } |
| 5195 if (is_one_byte) { |
| 5196 node = node->FilterOneByte(RegExpCompiler::kMaxRecursion, ignore_case); |
| 5197 // Do it again to propagate the new nodes to places where they were not |
| 5198 // put because they had not been calculated yet. |
| 5199 if (node != NULL) { |
| 5200 node = node->FilterOneByte(RegExpCompiler::kMaxRecursion, ignore_case); |
| 5201 } |
| 5202 } |
| 5203 |
| 5204 if (node == NULL) node = new(zone) EndNode(EndNode::BACKTRACK, zone); |
| 5205 data->node = node; |
| 5206 Analysis analysis(ignore_case, is_one_byte); |
| 5207 analysis.EnsureAnalyzed(node); |
| 5208 if (analysis.has_failed()) { |
| 5209 const char* error_message = analysis.error_message(); |
| 5210 return CompilationResult(error_message); |
| 5211 } |
| 5212 |
| 5213 // Bytecode regexp implementation. |
| 5214 |
| 5215 ZoneGrowableArray<uint8_t> buffer(zone, 1024); |
| 5216 BytecodeRegExpMacroAssembler* macro_assembler = |
| 5217 new(zone) BytecodeRegExpMacroAssembler(&buffer, zone); |
| 5218 |
| 5219 // Inserted here, instead of in Assembler, because it depends on information |
| 5220 // in the AST that isn't replicated in the Node structure. |
| 5221 static const intptr_t kMaxBacksearchLimit = 1024; |
| 5222 if (is_end_anchored && |
| 5223 !is_start_anchored && |
| 5224 max_length < kMaxBacksearchLimit) { |
| 5225 macro_assembler->SetCurrentPositionFromEnd(max_length); |
| 5226 } |
| 5227 |
| 5228 if (is_global) { |
| 5229 macro_assembler->set_global_mode( |
| 5230 (data->tree->min_match() > 0) |
| 5231 ? RegExpMacroAssembler::GLOBAL_NO_ZERO_LENGTH_CHECK |
| 5232 : RegExpMacroAssembler::GLOBAL); |
| 5233 } |
| 5234 |
| 5235 RegExpEngine::CompilationResult result = |
| 5236 compiler.Assemble(macro_assembler, |
| 5237 node, |
| 5238 data->capture_count, |
| 5239 pattern); |
| 5240 |
| 5241 if (FLAG_trace_irregexp) { |
| 5242 macro_assembler->PrintBlocks(); |
| 5243 } |
| 5244 |
| 5245 return result; |
| 5246 } |
| 5247 |
| 5248 |
5101 static void CreateSpecializedFunction(Zone* zone, | 5249 static void CreateSpecializedFunction(Zone* zone, |
5102 const JSRegExp& regexp, | 5250 const JSRegExp& regexp, |
5103 intptr_t specialization_cid, | 5251 intptr_t specialization_cid, |
5104 const Object& owner) { | 5252 const Object& owner) { |
5105 const intptr_t kParamCount = RegExpMacroAssembler::kParamCount; | 5253 const intptr_t kParamCount = RegExpMacroAssembler::kParamCount; |
5106 | 5254 |
5107 Function& fn = Function::Handle(zone, Function::New( | 5255 Function& fn = Function::Handle(zone, Function::New( |
5108 // Append the regexp pattern to the function name. | 5256 // Append the regexp pattern to the function name. |
5109 String::Handle(zone, Symbols::New( | 5257 String::Handle(zone, Symbols::New( |
5110 String::Handle(zone, String::Concat( | 5258 String::Handle(zone, String::Concat( |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5171 CreateSpecializedFunction(zone, regexp, kOneByteStringCid, owner); | 5319 CreateSpecializedFunction(zone, regexp, kOneByteStringCid, owner); |
5172 CreateSpecializedFunction(zone, regexp, kTwoByteStringCid, owner); | 5320 CreateSpecializedFunction(zone, regexp, kTwoByteStringCid, owner); |
5173 CreateSpecializedFunction(zone, regexp, kExternalOneByteStringCid, owner); | 5321 CreateSpecializedFunction(zone, regexp, kExternalOneByteStringCid, owner); |
5174 CreateSpecializedFunction(zone, regexp, kExternalTwoByteStringCid, owner); | 5322 CreateSpecializedFunction(zone, regexp, kExternalTwoByteStringCid, owner); |
5175 | 5323 |
5176 return regexp.raw(); | 5324 return regexp.raw(); |
5177 } | 5325 } |
5178 | 5326 |
5179 | 5327 |
5180 } // namespace dart | 5328 } // namespace dart |
OLD | NEW |