4264 {
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286 const intptr_t kMaxUnrolledMinMatches = 3;
4287
4288 const intptr_t kMaxUnrolledMaxMatches = 3;
4289 if (
max == 0)
return on_success;
4293 bool needs_capture_clearing = !capture_registers.is_empty();
4295
4296 if (body_can_be_empty) {
4297 body_start_reg =
compiler->AllocateRegister();
4299
4300
4301 {
4303 if (
min > 0 &&
min <= kMaxUnrolledMinMatches && limiter.ok_to_expand()) {
4305
4306
4307 RegExpNode* answer =
4309
4310
4311
4312 for (intptr_t
i = 0;
i <
min;
i++) {
4314 }
4315 return answer;
4316 }
4317 }
4318 if (
max <= kMaxUnrolledMaxMatches &&
min == 0) {
4321 if (limiter.ok_to_expand()) {
4322
4323 RegExpNode* answer = on_success;
4324 for (intptr_t
i = 0;
i <
max;
i++) {
4325 ChoiceNode* alternation = new (zone) ChoiceNode(2, zone);
4327 alternation->AddAlternative(
4329 alternation->AddAlternative(GuardedAlternative(on_success));
4330 } else {
4331 alternation->AddAlternative(GuardedAlternative(on_success));
4332 alternation->AddAlternative(
4334 }
4335 answer = alternation;
4336 if (not_at_start && !
compiler->read_backward()) {
4337 alternation->set_not_at_start();
4338 }
4339 }
4340 return answer;
4341 }
4342 }
4343 }
4344 bool has_min =
min > 0;
4346 bool needs_counter = has_min || has_max;
4347 intptr_t reg_ctr = needs_counter ?
compiler->AllocateRegister()
4349 LoopChoiceNode*
center =
new (zone)
4351 if (not_at_start && !
compiler->read_backward())
center->set_not_at_start();
4352 RegExpNode* loop_return =
4353 needs_counter ? static_cast<RegExpNode*>(
4355 : static_cast<RegExpNode*>(center);
4356 if (body_can_be_empty) {
4357
4358
4359 loop_return =
4361 }
4363 if (body_can_be_empty) {
4364
4365
4367 }
4368 if (needs_capture_clearing) {
4369
4371 }
4372 GuardedAlternative body_alt(body_node);
4373 if (has_max) {
4374 Guard* body_guard =
new (zone) Guard(reg_ctr,
Guard::LT,
max);
4375 body_alt.AddGuard(body_guard, zone);
4376 }
4377 GuardedAlternative rest_alt(on_success);
4378 if (has_min) {
4379 Guard* rest_guard =
new (zone) Guard(reg_ctr,
Guard::GEQ,
min);
4380 rest_alt.AddGuard(rest_guard, zone);
4381 }
4383 center->AddLoopAlternative(body_alt);
4384 center->AddContinueAlternative(rest_alt);
4385 } else {
4386 center->AddContinueAlternative(rest_alt);
4387 center->AddLoopAlternative(body_alt);
4388 }
4389 if (needs_counter) {
4391 } else {
4393 }
4394}
static ActionNode * EmptyMatchCheck(intptr_t start_register, intptr_t repetition_register, intptr_t repetition_limit, RegExpNode *on_success)
static ActionNode * SetRegister(intptr_t reg, intptr_t val, RegExpNode *on_success)
static ActionNode * IncrementRegister(intptr_t reg, RegExpNode *on_success)
static ActionNode * ClearCaptures(Interval range, RegExpNode *on_success)
static ActionNode * StorePosition(intptr_t reg, bool is_capture, RegExpNode *on_success)
static constexpr intptr_t kNoRegister
virtual RegExpNode * ToNode(RegExpCompiler *compiler, RegExpNode *on_success)
virtual RegExpNode * ToNode(RegExpCompiler *compiler, RegExpNode *on_success)=0
static constexpr bool kRegexpOptimization