Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(886)

Unified Diff: runtime/vm/regexp_assembler.cc

Issue 800433004: Use a typed array for the irregexp stack. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: naming Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/regexp_assembler.h ('k') | runtime/vm/symbols.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/regexp_assembler.cc
diff --git a/runtime/vm/regexp_assembler.cc b/runtime/vm/regexp_assembler.cc
index 4ecf4c19a5876d80ad45ff8c8e8e9ab6f5e80b8a..a494b1f9dfd431bfff9c261289d62db78bf7123b 100644
--- a/runtime/vm/regexp_assembler.cc
+++ b/runtime/vm/regexp_assembler.cc
@@ -36,6 +36,7 @@ DEFINE_FLAG(bool, trace_irregexp, false, "Trace irregexps");
static const intptr_t kInvalidTryIndex = CatchClauseNode::kInvalidTryIndex;
static const intptr_t kNoSourcePos = Scanner::kNoSourcePos;
+static const intptr_t kMinStackSize = 512;
void PrintUtf16(uint16_t c) {
@@ -90,6 +91,7 @@ IRRegExpMacroAssembler::IRRegExpMacroAssembler(
ic_data_array_(ic_data_array),
current_instruction_(NULL),
stack_(NULL),
+ stack_pointer_(NULL),
current_character_(NULL),
current_position_(NULL),
string_param_(NULL),
@@ -97,8 +99,7 @@ IRRegExpMacroAssembler::IRRegExpMacroAssembler(
start_index_param_(NULL),
registers_count_(0),
saved_registers_count_((capture_count + 1) * 2),
- stack_array_(GrowableObjectArray::ZoneHandle(
- isolate, GrowableObjectArray::New(16, Heap::kOld))),
+ stack_array_cell_(Array::ZoneHandle(isolate, Array::New(1, Heap::kOld))),
// The registers array is allocated at a fixed size after assembly.
registers_array_(TypedData::ZoneHandle(isolate, TypedData::null())) {
switch (specialization_cid) {
@@ -111,6 +112,12 @@ IRRegExpMacroAssembler::IRRegExpMacroAssembler(
InitializeLocals();
+ // Allocate an initial stack backing of the minimum stack size. The stack
+ // backing is indirectly referred to so we can reuse it on subsequent matches
+ // even in the case where the backing has been enlarged and thus reallocated.
+ stack_array_cell_.SetAt(0, TypedData::Handle(isolate,
+ TypedData::New(kTypedDataInt32ArrayCid, kMinStackSize / 4, Heap::kOld)));
+
// Create and generate all preset blocks.
entry_block_ =
new(isolate) GraphEntryInstr(
@@ -152,6 +159,7 @@ void IRRegExpMacroAssembler::InitializeLocals() {
// Create local variables and parameters.
stack_ = Local(Symbols::stack());
+ stack_pointer_ = Local(Symbols::stack_pointer());
registers_ = Local(Symbols::position_registers());
current_character_ = Local(Symbols::current_character());
current_position_ = Local(Symbols::current_position());
@@ -197,13 +205,13 @@ void IRRegExpMacroAssembler::GenerateEntryBlock() {
ClearRegisters(0, saved_registers_count_ - 1);
// Generate a local list variable to represent the backtracking stack.
- StoreLocal(stack_, Bind(new(I) ConstantInstr(stack_array_)));
- PushArgumentInstr* stack_push = PushLocal(stack_);
- PushArgumentInstr* zero_push = PushArgument(Bind(Uint64Constant(0)));
- Do(InstanceCall(InstanceCallDescriptor(
- Library::PrivateCoreLibName(Symbols::_setLength())),
- stack_push,
- zero_push));
+ PushArgumentInstr* stack_cell_push =
+ PushArgument(Bind(new(I) ConstantInstr(stack_array_cell_)));
+ StoreLocal(stack_, Bind(InstanceCall(
+ InstanceCallDescriptor::FromToken(Token::kINDEX),
+ stack_cell_push,
+ PushArgument(Bind(Uint64Constant(0))))));
+ StoreLocal(stack_pointer_, Bind(Int64Constant(-1)));
// Jump to the start block.
current_instruction_->Goto(start_block_);
@@ -222,7 +230,7 @@ void IRRegExpMacroAssembler::GenerateBacktrackBlock() {
PushArgumentInstr* block_offsets_push =
PushArgument(Bind(new(I) ConstantInstr(offsets)));
- PushArgumentInstr* block_id_push = PushArgument(PopStack());
+ PushArgumentInstr* block_id_push = PushArgument(Bind(PopStack()));
Value* offset_value =
Bind(InstanceCall(InstanceCallDescriptor::FromToken(Token::kINDEX),
@@ -897,20 +905,13 @@ void IRRegExpMacroAssembler::CheckGreedyLoop(BlockLabel* on_equal) {
BlockLabel fallthrough;
- PushArgumentInstr* stack_push = PushLocal(stack_);
- Definition* stack_tip_def = InstanceCall(
- InstanceCallDescriptor(String::ZoneHandle(
- I, Field::GetterSymbol(Symbols::last()))),
- stack_push);
+ Definition* head = PeekStack();
Definition* cur_pos_def = LoadLocal(current_position_);
-
- BranchOrBacktrack(Comparison(kNE, stack_tip_def, cur_pos_def),
+ BranchOrBacktrack(Comparison(kNE, head, cur_pos_def),
&fallthrough);
// Pop, throwing away the value.
- stack_push = PushLocal(stack_);
- Do(InstanceCall(InstanceCallDescriptor(Symbols::removeLast()),
- stack_push));
+ Do(PopStack());
BranchOrBacktrack(NULL, on_equal);
@@ -1527,7 +1528,7 @@ void IRRegExpMacroAssembler::LoadCurrentCharacter(intptr_t cp_offset,
void IRRegExpMacroAssembler::PopCurrentPosition() {
TAG();
- StoreLocal(current_position_, PopStack());
+ StoreLocal(current_position_, Bind(PopStack()));
}
@@ -1536,24 +1537,46 @@ void IRRegExpMacroAssembler::PopRegister(intptr_t reg) {
ASSERT(reg < registers_count_);
PushArgumentInstr* registers_push = PushLocal(registers_);
PushArgumentInstr* index_push = PushRegisterIndex(reg);
- PushArgumentInstr* pop_push = PushArgument(PopStack());
+ PushArgumentInstr* pop_push = PushArgument(Bind(PopStack()));
StoreRegister(registers_push, index_push, pop_push);
}
void IRRegExpMacroAssembler::PushStack(Definition *definition) {
PushArgumentInstr* stack_push = PushLocal(stack_);
+ PushArgumentInstr* stack_pointer_push = PushLocal(stack_pointer_);
+ StoreLocal(stack_pointer_,
+ Bind(Add(stack_pointer_push,
+ PushArgument(Bind(Uint64Constant(1))))));
+ stack_pointer_push = PushLocal(stack_pointer_);
+ // TODO(zerny): bind value and push could break stack discipline.
PushArgumentInstr* value_push = PushArgument(Bind(definition));
- Do(InstanceCall(InstanceCallDescriptor(Symbols::add()),
+ Do(InstanceCall(InstanceCallDescriptor::FromToken(Token::kASSIGN_INDEX),
stack_push,
+ stack_pointer_push,
value_push));
}
-Value* IRRegExpMacroAssembler::PopStack() {
+Definition* IRRegExpMacroAssembler::PopStack() {
+ PushArgumentInstr* stack_push = PushLocal(stack_);
+ PushArgumentInstr* stack_pointer_push1 = PushLocal(stack_pointer_);
+ PushArgumentInstr* stack_pointer_push2 = PushLocal(stack_pointer_);
+ StoreLocal(stack_pointer_,
+ Bind(Sub(stack_pointer_push2,
+ PushArgument(Bind(Uint64Constant(1))))));
+ return InstanceCall(InstanceCallDescriptor::FromToken(Token::kINDEX),
+ stack_push,
+ stack_pointer_push1);
+}
+
+
+Definition* IRRegExpMacroAssembler::PeekStack() {
PushArgumentInstr* stack_push = PushLocal(stack_);
- return Bind(InstanceCall(InstanceCallDescriptor(Symbols::removeLast()),
- stack_push));
+ PushArgumentInstr* stack_pointer_push = PushLocal(stack_pointer_);
+ return InstanceCall(InstanceCallDescriptor::FromToken(Token::kINDEX),
+ stack_push,
+ stack_pointer_push);
}
@@ -1571,6 +1594,7 @@ void IRRegExpMacroAssembler::PushBacktrack(BlockLabel* label) {
ConstantInstr* offset = Uint64Constant(indirect_target->indirect_id());
PushStack(offset);
+ CheckStackLimit();
}
@@ -1582,11 +1606,60 @@ void IRRegExpMacroAssembler::PushCurrentPosition() {
void IRRegExpMacroAssembler::PushRegister(intptr_t reg) {
TAG();
+ // TODO(zerny): Refactor PushStack so it can be reused here.
PushArgumentInstr* stack_push = PushLocal(stack_);
+ PushArgumentInstr* stack_pointer_push = PushLocal(stack_pointer_);
+ StoreLocal(stack_pointer_,
+ Bind(Add(stack_pointer_push,
+ PushArgument(Bind(Uint64Constant(1))))));
+ stack_pointer_push = PushLocal(stack_pointer_);
+ // TODO(zerny): bind value and push could break stack discipline.
PushArgumentInstr* value_push = PushArgument(LoadRegister(reg));
- Do(InstanceCall(InstanceCallDescriptor(Symbols::add()),
+ Do(InstanceCall(InstanceCallDescriptor::FromToken(Token::kASSIGN_INDEX),
stack_push,
+ stack_pointer_push,
value_push));
+ CheckStackLimit();
+}
+
+
+// Checks that (stack.capacity - stack_limit_slack) > stack_pointer.
+// This ensures that up to stack_limit_slack stack pushes can be
+// done without exhausting the stack space. If the check fails the
+// stack will be grown.
+void IRRegExpMacroAssembler::CheckStackLimit() {
+ TAG();
+ PushArgumentInstr* stack_push = PushLocal(stack_);
+ PushArgumentInstr* length_push = PushArgument(Bind(InstanceCall(
+ InstanceCallDescriptor(
+ String::ZoneHandle(Field::GetterSymbol(Symbols::Length()))),
+ stack_push)));
+ PushArgumentInstr* capacity_push = PushArgument(Bind(Sub(
+ length_push,
+ PushArgument(Bind(Uint64Constant(stack_limit_slack()))))));
+ PushArgumentInstr* stack_pointer_push = PushLocal(stack_pointer_);
+ BranchInstr* branch = new(I) BranchInstr(
+ Comparison(kGT, capacity_push, stack_pointer_push));
+ CloseBlockWith(branch);
+
+ BlockLabel grow_stack;
+ BlockLabel fallthrough;
+ *branch->true_successor_address() =
+ TargetWithJoinGoto(fallthrough.block());
+ *branch->false_successor_address() =
+ TargetWithJoinGoto(grow_stack.block());
+
+ BindBlock(&grow_stack);
+ GrowStack();
+
+ BindBlock(&fallthrough);
+}
+
+
+void IRRegExpMacroAssembler::GrowStack() {
+ TAG();
+ Value* cell = Bind(new(I) ConstantInstr(stack_array_cell_));
+ StoreLocal(stack_, Bind(new(I) GrowRegExpStackInstr(cell)));
}
@@ -1595,19 +1668,11 @@ void IRRegExpMacroAssembler::ReadCurrentPositionFromRegister(intptr_t reg) {
StoreLocal(current_position_, LoadRegister(reg));
}
-// Resets the size of the stack to the value stored in reg.
+// Resets the tip of the stack to the value stored in reg.
void IRRegExpMacroAssembler::ReadStackPointerFromRegister(intptr_t reg) {
TAG();
ASSERT(reg < registers_count_);
-
- PushArgumentInstr* stack_push = PushLocal(stack_);
- PushArgumentInstr* length_push = PushArgument(LoadRegister(reg));
-
- Do(InstanceCall(
- InstanceCallDescriptor(
- String::ZoneHandle(I, Field::SetterSymbol(Symbols::Length()))),
- stack_push,
- length_push));
+ StoreLocal(stack_pointer_, LoadRegister(reg));
}
void IRRegExpMacroAssembler::SetCurrentPositionFromEnd(intptr_t by) {
@@ -1689,12 +1754,8 @@ void IRRegExpMacroAssembler::WriteStackPointerToRegister(intptr_t reg) {
PushArgumentInstr* registers_push = PushLocal(registers_);
PushArgumentInstr* index_push = PushRegisterIndex(reg);
- PushArgumentInstr* stack_push = PushLocal(stack_);
- PushArgumentInstr* length_push =
- PushArgument(Bind(InstanceCall(InstanceCallDescriptor(
- String::ZoneHandle(I, Field::GetterSymbol(Symbols::Length()))),
- stack_push)));
- StoreRegister(registers_push, index_push, length_push);
+ PushArgumentInstr* tip_push = PushLocal(stack_pointer_);
+ StoreRegister(registers_push, index_push, tip_push);
}
« no previous file with comments | « runtime/vm/regexp_assembler.h ('k') | runtime/vm/symbols.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698