Skip to content

Commit 881fe78

Browse files
Erik Corrytargos
authored andcommitted
deps: V8: cherry-pick 0dd2318b5237
Original commit message: [regexp] Remove DeferredAction class. We can just chain up the traces and use the regular ActionNodes that we already have to represent the deferred actions. Also simplifies the ActionNodes a little. No functional change intended. Reduce the size of the Trace from 128->120 bytes. This is a stack allocated struct so to avoid stack overflows after adding the next_ field I am reducing it back down to 120 bytes by rearranging and shrinking fields. Change-Id: I6dca9946e035e9b22798e160b8fadaeca61f4955 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/6512931 Reviewed-by: Patrick Thier <pthier@chromium.org> Commit-Queue: Erik Corry <erikcorry@chromium.org> Cr-Commit-Position: refs/heads/main@{#100092} Refs: v8/v8@0dd2318 PR-URL: #60732 Fixes: #60030 Reviewed-By: Michaël Zasso <targos@protonmail.com> Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
1 parent 457c33e commit 881fe78

File tree

6 files changed

+190
-206
lines changed

6 files changed

+190
-206
lines changed

common.gypi

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838

3939
# Reset this number to 0 on major V8 upgrades.
4040
# Increment by one for each non-official patch applied to deps/v8.
41-
'v8_embedder_string': '-node.34',
41+
'v8_embedder_string': '-node.35',
4242

4343
##### V8 defaults for Node.js #####
4444

deps/v8/src/regexp/regexp-compiler-tonode.cc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1248,9 +1248,9 @@ RegExpNode* RegExpCapture::ToNode(RegExpTree* body, int index,
12481248
int start_reg = RegExpCapture::StartRegister(index);
12491249
int end_reg = RegExpCapture::EndRegister(index);
12501250
if (compiler->read_backward()) std::swap(start_reg, end_reg);
1251-
RegExpNode* store_end = ActionNode::StorePosition(end_reg, true, on_success);
1251+
RegExpNode* store_end = ActionNode::ClearPosition(end_reg, on_success);
12521252
RegExpNode* body_node = body->ToNode(compiler, store_end);
1253-
return ActionNode::StorePosition(start_reg, true, body_node);
1253+
return ActionNode::ClearPosition(start_reg, body_node);
12541254
}
12551255

12561256
namespace {
@@ -2039,7 +2039,7 @@ RegExpNode* RegExpQuantifier::ToNode(int min, int max, bool is_greedy,
20392039
if (body_can_be_empty) {
20402040
// If the body can be empty we need to store the start position
20412041
// so we can bail out if it was empty.
2042-
body_node = ActionNode::StorePosition(body_start_reg, false, body_node);
2042+
body_node = ActionNode::RestorePosition(body_start_reg, body_node);
20432043
}
20442044
if (needs_capture_clearing) {
20452045
// Before entering the body of this loop we need to clear captures.

deps/v8/src/regexp/regexp-compiler.cc

Lines changed: 57 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -294,30 +294,20 @@ RegExpCompiler::CompilationResult RegExpCompiler::Assemble(
294294
return {code, next_register_};
295295
}
296296

297-
bool Trace::DeferredAction::Mentions(int that) {
298-
if (action_type() == ActionNode::CLEAR_CAPTURES) {
299-
Interval range = static_cast<DeferredClearCaptures*>(this)->range();
300-
return range.Contains(that);
301-
} else {
302-
return reg() == that;
303-
}
304-
}
305-
306-
bool Trace::mentions_reg(int reg) {
307-
for (DeferredAction* action = actions_; action != nullptr;
308-
action = action->next()) {
309-
if (action->Mentions(reg)) return true;
297+
bool Trace::mentions_reg(int reg) const {
298+
for (auto trace : *this) {
299+
if (trace->has_action() && trace->action()->Mentions(reg)) return true;
310300
}
311301
return false;
312302
}
313303

314-
bool Trace::GetStoredPosition(int reg, int* cp_offset) {
304+
bool Trace::GetStoredPosition(int reg, int* cp_offset) const {
315305
DCHECK_EQ(0, *cp_offset);
316-
for (DeferredAction* action = actions_; action != nullptr;
317-
action = action->next()) {
318-
if (action->Mentions(reg)) {
319-
if (action->action_type() == ActionNode::STORE_POSITION) {
320-
*cp_offset = static_cast<DeferredCapture*>(action)->cp_offset();
306+
for (auto trace : *this) {
307+
if (trace->has_action() && trace->action()->Mentions(reg)) {
308+
if (trace->action_->action_type() == ActionNode::CLEAR_POSITION ||
309+
trace->action_->action_type() == ActionNode::RESTORE_POSITION) {
310+
*cp_offset = trace->next_->cp_offset();
321311
return true;
322312
} else {
323313
return false;
@@ -363,16 +353,13 @@ class DynamicBitSet : public ZoneObject {
363353
int Trace::FindAffectedRegisters(DynamicBitSet* affected_registers,
364354
Zone* zone) {
365355
int max_register = RegExpCompiler::kNoRegister;
366-
for (DeferredAction* action = actions_; action != nullptr;
367-
action = action->next()) {
368-
if (action->action_type() == ActionNode::CLEAR_CAPTURES) {
369-
Interval range = static_cast<DeferredClearCaptures*>(action)->range();
370-
for (int i = range.from(); i <= range.to(); i++)
356+
for (auto trace : *this) {
357+
if (ActionNode* action = trace->action_) {
358+
int to = action->register_to();
359+
for (int i = action->register_from(); i <= to; i++) {
371360
affected_registers->Set(i, zone);
372-
if (range.to() > max_register) max_register = range.to();
373-
} else {
374-
affected_registers->Set(action->reg(), zone);
375-
if (action->reg() > max_register) max_register = action->reg();
361+
}
362+
if (to > max_register) max_register = to;
376363
}
377364
}
378365
return max_register;
@@ -420,15 +407,14 @@ void Trace::PerformDeferredActions(RegExpMacroAssembler* assembler,
420407
int store_position = kNoStore;
421408
// This is a little tricky because we are scanning the actions in reverse
422409
// historical order (newest first).
423-
for (DeferredAction* action = actions_; action != nullptr;
424-
action = action->next()) {
410+
for (auto trace : *this) {
411+
ActionNode* action = trace->action_;
412+
if (!action) continue;
425413
if (action->Mentions(reg)) {
426414
switch (action->action_type()) {
427415
case ActionNode::SET_REGISTER_FOR_LOOP: {
428-
Trace::DeferredSetRegisterForLoop* psr =
429-
static_cast<Trace::DeferredSetRegisterForLoop*>(action);
430416
if (!absolute) {
431-
value += psr->value();
417+
value += action->value();
432418
absolute = true;
433419
}
434420
// SET_REGISTER_FOR_LOOP is only used for newly introduced loop
@@ -449,11 +435,10 @@ void Trace::PerformDeferredActions(RegExpMacroAssembler* assembler,
449435
DCHECK(!clear);
450436
undo_action = RESTORE;
451437
break;
452-
case ActionNode::STORE_POSITION: {
453-
Trace::DeferredCapture* pc =
454-
static_cast<Trace::DeferredCapture*>(action);
438+
case ActionNode::CLEAR_POSITION:
439+
case ActionNode::RESTORE_POSITION: {
455440
if (!clear && store_position == kNoStore) {
456-
store_position = pc->cp_offset();
441+
store_position = trace->next()->cp_offset();
457442
}
458443

459444
// For captures we know that stores and clears alternate.
@@ -466,7 +451,11 @@ void Trace::PerformDeferredActions(RegExpMacroAssembler* assembler,
466451
// will set it again or fail.
467452
undo_action = IGNORE;
468453
} else {
469-
undo_action = pc->is_capture() ? CLEAR : RESTORE;
454+
if (action->action_type() == ActionNode::CLEAR_POSITION) {
455+
undo_action = CLEAR;
456+
} else {
457+
undo_action = RESTORE;
458+
}
470459
}
471460
DCHECK(!absolute);
472461
DCHECK_EQ(value, 0);
@@ -527,7 +516,7 @@ void Trace::Flush(RegExpCompiler* compiler, RegExpNode* successor) {
527516

528517
DCHECK(!is_trivial());
529518

530-
if (actions_ == nullptr && backtrack() == nullptr) {
519+
if (!has_any_actions() && backtrack() == nullptr) {
531520
// Here we just have some deferred cp advances to fix and we are back to
532521
// a normal situation. We may also have to forget some information gained
533522
// through a quick check that was already performed.
@@ -638,35 +627,26 @@ void GuardedAlternative::AddGuard(Guard* guard, Zone* zone) {
638627

639628
ActionNode* ActionNode::SetRegisterForLoop(int reg, int val,
640629
RegExpNode* on_success) {
641-
ActionNode* result =
642-
on_success->zone()->New<ActionNode>(SET_REGISTER_FOR_LOOP, on_success);
643-
result->data_.u_store_register.reg = reg;
644-
result->data_.u_store_register.value = val;
645-
return result;
630+
return on_success->zone()->New<ActionNode>(SET_REGISTER_FOR_LOOP, on_success,
631+
reg, reg, val);
646632
}
647633

648634
ActionNode* ActionNode::IncrementRegister(int reg, RegExpNode* on_success) {
649-
ActionNode* result =
650-
on_success->zone()->New<ActionNode>(INCREMENT_REGISTER, on_success);
651-
result->data_.u_increment_register.reg = reg;
652-
return result;
635+
return on_success->zone()->New<ActionNode>(INCREMENT_REGISTER, on_success,
636+
reg);
653637
}
654638

655-
ActionNode* ActionNode::StorePosition(int reg, bool is_capture,
656-
RegExpNode* on_success) {
657-
ActionNode* result =
658-
on_success->zone()->New<ActionNode>(STORE_POSITION, on_success);
659-
result->data_.u_position_register.reg = reg;
660-
result->data_.u_position_register.is_capture = is_capture;
661-
return result;
639+
ActionNode* ActionNode::ClearPosition(int reg, RegExpNode* on_success) {
640+
return on_success->zone()->New<ActionNode>(CLEAR_POSITION, on_success, reg);
641+
}
642+
643+
ActionNode* ActionNode::RestorePosition(int reg, RegExpNode* on_success) {
644+
return on_success->zone()->New<ActionNode>(RESTORE_POSITION, on_success, reg);
662645
}
663646

664647
ActionNode* ActionNode::ClearCaptures(Interval range, RegExpNode* on_success) {
665-
ActionNode* result =
666-
on_success->zone()->New<ActionNode>(CLEAR_CAPTURES, on_success);
667-
result->data_.u_clear_captures.range_from = range.from();
668-
result->data_.u_clear_captures.range_to = range.to();
669-
return result;
648+
return on_success->zone()->New<ActionNode>(CLEAR_CAPTURES, on_success,
649+
range.from(), range.to());
670650
}
671651

672652
ActionNode* ActionNode::BeginPositiveSubmatch(int stack_reg, int position_reg,
@@ -2373,7 +2353,7 @@ void AssertionNode::Emit(RegExpCompiler* compiler, Trace* trace) {
23732353

23742354
namespace {
23752355

2376-
bool DeterminedAlready(QuickCheckDetails* quick_check, int offset) {
2356+
bool DeterminedAlready(const QuickCheckDetails* quick_check, int offset) {
23772357
if (quick_check == nullptr) return false;
23782358
if (offset >= quick_check->characters()) return false;
23792359
return quick_check->positions(offset)->determines_perfectly;
@@ -2423,7 +2403,7 @@ void TextNode::TextEmitPass(RegExpCompiler* compiler, TextEmitPassType pass,
24232403
Isolate* isolate = assembler->isolate();
24242404
bool one_byte = compiler->one_byte();
24252405
Label* backtrack = trace->backtrack();
2426-
QuickCheckDetails* quick_check = trace->quick_check_performed();
2406+
const QuickCheckDetails* quick_check = trace->quick_check_performed();
24272407
int element_count = elements()->length();
24282408
int backward_offset = read_backward() ? -Length() : 0;
24292409
for (int i = preloaded ? 0 : element_count - 1; i >= 0; i--) {
@@ -3206,7 +3186,7 @@ void ChoiceNode::Emit(RegExpCompiler* compiler, Trace* trace) {
32063186

32073187
// For loop nodes we already flushed (see LoopChoiceNode::Emit), but for
32083188
// other choice nodes we only flush if we are out of code size budget.
3209-
if (trace->flush_budget() == 0 && trace->actions() != nullptr) {
3189+
if (trace->flush_budget() == 0 && trace->has_any_actions()) {
32103190
trace->Flush(compiler, this);
32113191
return;
32123192
}
@@ -3239,7 +3219,7 @@ void ChoiceNode::Emit(RegExpCompiler* compiler, Trace* trace) {
32393219
// If there are actions to be flushed we have to limit how many times
32403220
// they are flushed. Take the budget of the parent trace and distribute
32413221
// it fairly amongst the children.
3242-
if (new_trace.actions() != nullptr) {
3222+
if (new_trace.has_any_actions()) {
32433223
new_trace.set_flush_budget(new_flush_budget);
32443224
}
32453225
bool next_expects_preload =
@@ -3407,7 +3387,7 @@ void ChoiceNode::EmitChoices(RegExpCompiler* compiler,
34073387
generate_full_check_inline = true;
34083388
}
34093389
if (generate_full_check_inline) {
3410-
if (new_trace.actions() != nullptr) {
3390+
if (new_trace.has_any_actions()) {
34113391
new_trace.set_flush_budget(new_flush_budget);
34123392
}
34133393
for (int j = 0; j < guard_count; j++) {
@@ -3468,42 +3448,26 @@ void ActionNode::Emit(RegExpCompiler* compiler, Trace* trace) {
34683448
RecursionCheck rc(compiler);
34693449

34703450
switch (action_type_) {
3471-
case STORE_POSITION: {
3472-
Trace::DeferredCapture new_capture(data_.u_position_register.reg,
3473-
data_.u_position_register.is_capture,
3474-
trace);
3475-
Trace new_trace = *trace;
3476-
new_trace.add_action(&new_capture);
3477-
on_success()->Emit(compiler, &new_trace);
3478-
break;
3479-
}
3480-
case INCREMENT_REGISTER: {
3481-
Trace::DeferredIncrementRegister new_increment(
3482-
data_.u_increment_register.reg);
3483-
Trace new_trace = *trace;
3484-
new_trace.add_action(&new_increment);
3485-
on_success()->Emit(compiler, &new_trace);
3486-
break;
3487-
}
3488-
case SET_REGISTER_FOR_LOOP: {
3489-
Trace::DeferredSetRegisterForLoop new_set(data_.u_store_register.reg,
3490-
data_.u_store_register.value);
3491-
Trace new_trace = *trace;
3492-
new_trace.add_action(&new_set);
3493-
on_success()->Emit(compiler, &new_trace);
3494-
break;
3495-
}
3451+
// Start with the actions we know how to defer. These are just recorded in
3452+
// the new trace, no code is emitted right now. (If we backtrack then we
3453+
// don't have to perform and undo these actions.)
3454+
case CLEAR_POSITION:
3455+
case RESTORE_POSITION:
3456+
case INCREMENT_REGISTER:
3457+
case SET_REGISTER_FOR_LOOP:
34963458
case CLEAR_CAPTURES: {
3497-
Trace::DeferredClearCaptures new_capture(Interval(
3498-
data_.u_clear_captures.range_from, data_.u_clear_captures.range_to));
34993459
Trace new_trace = *trace;
3500-
new_trace.add_action(&new_capture);
3460+
new_trace.add_action(this);
35013461
on_success()->Emit(compiler, &new_trace);
35023462
break;
35033463
}
3464+
// We don't yet have the ability to defer these.
35043465
case BEGIN_POSITIVE_SUBMATCH:
35053466
case BEGIN_NEGATIVE_SUBMATCH:
35063467
if (!trace->is_trivial()) {
3468+
// Complex situation: Flush the trace state to the assembler and
3469+
// generate a generic version of this action. This call will
3470+
// recurse back to the else clause here.
35073471
trace->Flush(compiler, this);
35083472
} else {
35093473
assembler->WriteCurrentPositionToRegister(

0 commit comments

Comments
 (0)