| Index: runtime/vm/regexp_assembler.cc
|
| diff --git a/runtime/vm/regexp_assembler.cc b/runtime/vm/regexp_assembler.cc
|
| index 4285e12ab52cbf08011f7427324bf132dba1ba6f..c5e4ba3a5f3edcac8e41647f0e535715d534284b 100644
|
| --- a/runtime/vm/regexp_assembler.cc
|
| +++ b/runtime/vm/regexp_assembler.cc
|
| @@ -34,8 +34,8 @@ namespace dart {
|
| DEFINE_FLAG(bool, trace_irregexp, false, "Trace irregexps");
|
|
|
|
|
| -static const intptr_t kInvalidTryIndex = -1;
|
| -static const intptr_t kNoTokenPos = -1;
|
| +static const intptr_t kInvalidTryIndex = CatchClauseNode::kInvalidTryIndex;
|
| +static const intptr_t kNoSourcePos = Scanner::kNoSourcePos;
|
|
|
|
|
| void PrintUtf16(uint16_t c) {
|
| @@ -112,8 +112,8 @@ IRRegExpMacroAssembler::IRRegExpMacroAssembler(
|
| entry_block_ =
|
| new(isolate) GraphEntryInstr(
|
| parsed_function_,
|
| - new(isolate) TargetEntryInstr(block_id_.Alloc(), kInvalidTryIndex),
|
| - Isolate::kNoDeoptId);
|
| + new(isolate) TargetEntryInstr(
|
| + block_id_.Alloc(), kInvalidTryIndex), Isolate::kNoDeoptId);
|
| start_block_ =
|
| new(isolate) JoinEntryInstr(block_id_.Alloc(), kInvalidTryIndex);
|
| success_block_ =
|
| @@ -123,6 +123,11 @@ IRRegExpMacroAssembler::IRRegExpMacroAssembler(
|
| exit_block_ =
|
| new(isolate) JoinEntryInstr(block_id_.Alloc(), kInvalidTryIndex);
|
|
|
| + // Allocate offsets table mapping ids of backtracking blocks to addresses.
|
| + GrowableObjectArray& offsets = GrowableObjectArray::ZoneHandle(
|
| + isolate, GrowableObjectArray::New(Heap::kOld));
|
| + entry_block_->set_indirect_entry_offsets(&offsets);
|
| +
|
| GenerateEntryBlock();
|
| GenerateSuccessBlock();
|
| GenerateBacktrackBlock();
|
| @@ -254,7 +259,7 @@ void IRRegExpMacroAssembler::GenerateSuccessBlock() {
|
| PRINT(PushLocal(result_));
|
|
|
| // Return true on success.
|
| - AppendInstruction(new(I) ReturnInstr(kNoTokenPos, Bind(LoadLocal(result_))));
|
| + AppendInstruction(new(I) ReturnInstr(kNoSourcePos, Bind(LoadLocal(result_))));
|
| }
|
|
|
|
|
| @@ -263,7 +268,7 @@ void IRRegExpMacroAssembler::GenerateExitBlock() {
|
| TAG();
|
|
|
| // Return false on failure.
|
| - AppendInstruction(new(I) ReturnInstr(kNoTokenPos, Bind(LoadLocal(result_))));
|
| + AppendInstruction(new(I) ReturnInstr(kNoSourcePos, Bind(LoadLocal(result_))));
|
| }
|
|
|
|
|
| @@ -351,7 +356,7 @@ LocalVariable* IRRegExpMacroAssembler::Parameter(const String& name,
|
| intptr_t index) const {
|
| const Type& local_type = Type::ZoneHandle(I, Type::DynamicType());
|
| LocalVariable* local =
|
| - new(I) LocalVariable(kNoTokenPos, name, local_type);
|
| + new(I) LocalVariable(kNoSourcePos, name, local_type);
|
|
|
| intptr_t param_frame_index = kParamEndSlotFromFp + kParamCount - index;
|
| local->set_index(param_frame_index);
|
| @@ -363,7 +368,7 @@ LocalVariable* IRRegExpMacroAssembler::Parameter(const String& name,
|
| LocalVariable* IRRegExpMacroAssembler::Local(const String& name) {
|
| const Type& local_type = Type::ZoneHandle(I, Type::DynamicType());
|
| LocalVariable* local =
|
| - new(I) LocalVariable(kNoTokenPos, name, local_type);
|
| + new(I) LocalVariable(kNoSourcePos, name, local_type);
|
| local->set_index(GetNextLocalIndex());
|
|
|
| return local;
|
| @@ -451,7 +456,7 @@ ComparisonInstr* IRRegExpMacroAssembler::Comparison(
|
| rhs_push));
|
| Value* rhs_value = Bind(BoolConstant(true));
|
|
|
| - return new(I) StrictCompareInstr(kNoTokenPos, strict_comparison,
|
| + return new(I) StrictCompareInstr(kNoSourcePos, strict_comparison,
|
| lhs_value, rhs_value, true);
|
| }
|
|
|
| @@ -491,7 +496,7 @@ StaticCallInstr* IRRegExpMacroAssembler::StaticCall(
|
| StaticCallInstr* IRRegExpMacroAssembler::StaticCall(
|
| const Function& function,
|
| ZoneGrowableArray<PushArgumentInstr*>* arguments) const {
|
| - return new(I) StaticCallInstr(kNoTokenPos,
|
| + return new(I) StaticCallInstr(kNoSourcePos,
|
| function,
|
| Object::null_array(),
|
| arguments,
|
| @@ -542,7 +547,7 @@ InstanceCallInstr* IRRegExpMacroAssembler::InstanceCall(
|
| const InstanceCallDescriptor& desc,
|
| ZoneGrowableArray<PushArgumentInstr*> *arguments) const {
|
| return
|
| - new(I) InstanceCallInstr(kNoTokenPos,
|
| + new(I) InstanceCallInstr(kNoSourcePos,
|
| desc.name,
|
| desc.token_kind,
|
| arguments,
|
| @@ -725,8 +730,7 @@ void IRRegExpMacroAssembler::Backtrack() {
|
| TAG();
|
| CheckPreemption();
|
|
|
| - GrowableObjectArray& offsets = GrowableObjectArray::ZoneHandle(
|
| - I, GrowableObjectArray::New(Heap::kOld));
|
| + const GrowableObjectArray& offsets = *entry_block_->indirect_entry_offsets();
|
|
|
| PushArgumentInstr* block_offsets_push =
|
| PushArgument(Bind(new(I) ConstantInstr(offsets)));
|
| @@ -737,7 +741,7 @@ void IRRegExpMacroAssembler::Backtrack() {
|
| block_offsets_push,
|
| block_id_push));
|
|
|
| - IndirectGotoInstr* igoto = new(I) IndirectGotoInstr(&offsets, offset_value);
|
| + IndirectGotoInstr* igoto = new(I) IndirectGotoInstr(offset_value);
|
| CloseBlockWith(igoto);
|
| igotos_.Add(igoto);
|
| }
|
| @@ -779,43 +783,30 @@ LocalVariable* IRRegExpMacroAssembler::position_register(intptr_t index) {
|
| }
|
|
|
|
|
| -// TODO(zerny): Move the offset table outside to avoid having to keep
|
| -// the assembler around until after code generation; both function or regexp
|
| -// would work.
|
| -void IRRegExpMacroAssembler::FinalizeBlockOffsetTable() {
|
| - for (intptr_t i = 0; i < igotos_.length(); i++) {
|
| - IndirectGotoInstr* igoto = igotos_[i];
|
| - igoto->SetOffsetCount(I, indirect_id_.Count());
|
| -
|
| - for (intptr_t j = 0; j < igoto->SuccessorCount(); j++) {
|
| - TargetEntryInstr* target = igoto->SuccessorAt(j);
|
| -
|
| - // Optimizations might have modified the immediate target block, but
|
| - // it must end with a goto to the indirect entry.
|
| - Instruction* instr = target;
|
| - while (instr != NULL && !instr->IsGoto()) {
|
| - instr = instr->next();
|
| - }
|
| - ASSERT(instr->IsGoto());
|
| -
|
| - IndirectEntryInstr* ientry =
|
| - instr->AsGoto()->successor()->AsIndirectEntry();
|
| - ASSERT(ientry != NULL);
|
| -
|
| - // The intermediate block was possibly compacted, check both it and the
|
| - // final indirect entry for a valid offset. If neither are valid, then
|
| - // the indirect entry is unreachable.
|
| - intptr_t offset =
|
| - (target->offset() > 0) ? target->offset() : ientry->offset();
|
| - if (offset > 0) {
|
| - intptr_t adjusted_offset =
|
| - offset - Assembler::EntryPointToPcMarkerOffset();
|
| - igoto->SetOffsetAt(I, ientry->indirect_id(), adjusted_offset);
|
| - }
|
| +void IRRegExpMacroAssembler::FinalizeBlockOffsetTable(Isolate* isolate,
|
| + GraphEntryInstr* graph) {
|
| + const GrowableArray<IndirectEntryInstr*>& entries = graph->indirect_entries();
|
| + const intptr_t count = entries.length();
|
| + GrowableObjectArray* offsets = graph->indirect_entry_offsets();
|
| + if (offsets->Capacity() < count) {
|
| + offsets->Grow(count, Heap::kOld);
|
| + }
|
| + if (offsets->Length() < count) {
|
| + offsets->SetLength(count);
|
| + }
|
| + for (intptr_t i = 0; i < count; ++i) {
|
| + IndirectEntryInstr* entry = entries[i];
|
| + if (entry->offset() <= 0) {
|
| + // An invalid offset signifies an unreachable block.
|
| + // TODO(zerny): We should guard against usage of an invalid index.
|
| + continue;
|
| }
|
| + intptr_t offset = entry->offset() - Assembler::EntryPointToPcMarkerOffset();
|
| + offsets->SetAt(i, Smi::ZoneHandle(isolate, Smi::New(offset)));
|
| }
|
| }
|
|
|
| +
|
| void IRRegExpMacroAssembler::FinalizeIndirectGotos() {
|
| for (intptr_t i = 0; i < igotos_.length(); i++) {
|
| for (intptr_t j = 0; j < entry_block_->indirect_entries().length(); j++) {
|
| @@ -1774,7 +1765,7 @@ IndirectEntryInstr* IRRegExpMacroAssembler::IndirectWithJoinGoto(
|
|
|
| void IRRegExpMacroAssembler::CheckPreemption() {
|
| TAG();
|
| - AppendInstruction(new(I) CheckStackOverflowInstr(kNoTokenPos, 0));
|
| + AppendInstruction(new(I) CheckStackOverflowInstr(kNoSourcePos, 0));
|
| }
|
|
|
|
|
|
|