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

Side by Side Diff: runtime/vm/regexp_assembler.cc

Issue 716163003: Use one offsets table per generated irregexp matching function. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: comments Created 6 years, 1 month 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/regexp_assembler.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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_assembler.h" 5 #include "vm/regexp_assembler.h"
6 6
7 #include "vm/bit_vector.h" 7 #include "vm/bit_vector.h"
8 #include "vm/compiler.h" 8 #include "vm/compiler.h"
9 #include "vm/dart_entry.h" 9 #include "vm/dart_entry.h"
10 #include "vm/flow_graph_builder.h" 10 #include "vm/flow_graph_builder.h"
(...skipping 16 matching lines...) Expand all
27 String::Handle(String::New("TAG: ")), \ 27 String::Handle(String::New("TAG: ")), \
28 String::Handle(String::New(__FUNCTION__)), Heap::kOld)))))); 28 String::Handle(String::New(__FUNCTION__)), Heap::kOld))))));
29 29
30 #define PRINT(arg) if (FLAG_trace_irregexp) { Print(arg); } 30 #define PRINT(arg) if (FLAG_trace_irregexp) { Print(arg); }
31 31
32 namespace dart { 32 namespace dart {
33 33
34 DEFINE_FLAG(bool, trace_irregexp, false, "Trace irregexps"); 34 DEFINE_FLAG(bool, trace_irregexp, false, "Trace irregexps");
35 35
36 36
37 static const intptr_t kInvalidTryIndex = -1; 37 static const intptr_t kInvalidTryIndex = CatchClauseNode::kInvalidTryIndex;
38 static const intptr_t kNoTokenPos = -1; 38 static const intptr_t kNoSourcePos = Scanner::kNoSourcePos;
39 39
40 40
41 void PrintUtf16(uint16_t c) { 41 void PrintUtf16(uint16_t c) {
42 const char* format = (0x20 <= c && c <= 0x7F) ? 42 const char* format = (0x20 <= c && c <= 0x7F) ?
43 "%c" : (c <= 0xff) ? "\\x%02x" : "\\u%04x"; 43 "%c" : (c <= 0xff) ? "\\x%02x" : "\\u%04x";
44 OS::Print(format, c); 44 OS::Print(format, c);
45 } 45 }
46 46
47 47
48 /* 48 /*
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
105 case kExternalTwoByteStringCid: mode_ = UC16; break; 105 case kExternalTwoByteStringCid: mode_ = UC16; break;
106 default: UNREACHABLE(); 106 default: UNREACHABLE();
107 } 107 }
108 108
109 InitializeLocals(); 109 InitializeLocals();
110 110
111 // Create and generate all preset blocks. 111 // Create and generate all preset blocks.
112 entry_block_ = 112 entry_block_ =
113 new(isolate) GraphEntryInstr( 113 new(isolate) GraphEntryInstr(
114 parsed_function_, 114 parsed_function_,
115 new(isolate) TargetEntryInstr(block_id_.Alloc(), kInvalidTryIndex), 115 new(isolate) TargetEntryInstr(
116 Isolate::kNoDeoptId); 116 block_id_.Alloc(), kInvalidTryIndex), Isolate::kNoDeoptId);
117 start_block_ = 117 start_block_ =
118 new(isolate) JoinEntryInstr(block_id_.Alloc(), kInvalidTryIndex); 118 new(isolate) JoinEntryInstr(block_id_.Alloc(), kInvalidTryIndex);
119 success_block_ = 119 success_block_ =
120 new(isolate) JoinEntryInstr(block_id_.Alloc(), kInvalidTryIndex); 120 new(isolate) JoinEntryInstr(block_id_.Alloc(), kInvalidTryIndex);
121 backtrack_block_ = 121 backtrack_block_ =
122 new(isolate) JoinEntryInstr(block_id_.Alloc(), kInvalidTryIndex); 122 new(isolate) JoinEntryInstr(block_id_.Alloc(), kInvalidTryIndex);
123 exit_block_ = 123 exit_block_ =
124 new(isolate) JoinEntryInstr(block_id_.Alloc(), kInvalidTryIndex); 124 new(isolate) JoinEntryInstr(block_id_.Alloc(), kInvalidTryIndex);
125 125
126 // Allocate offsets table mapping ids of backtracking blocks to addresses.
127 GrowableObjectArray& offsets = GrowableObjectArray::ZoneHandle(
128 isolate, GrowableObjectArray::New(Heap::kOld));
129 entry_block_->set_indirect_entry_offsets(&offsets);
130
126 GenerateEntryBlock(); 131 GenerateEntryBlock();
127 GenerateSuccessBlock(); 132 GenerateSuccessBlock();
128 GenerateBacktrackBlock(); 133 GenerateBacktrackBlock();
129 GenerateExitBlock(); 134 GenerateExitBlock();
130 135
131 blocks_.Add(entry_block_); 136 blocks_.Add(entry_block_);
132 blocks_.Add(entry_block_->normal_entry()); 137 blocks_.Add(entry_block_->normal_entry());
133 blocks_.Add(start_block_); 138 blocks_.Add(start_block_);
134 blocks_.Add(success_block_); 139 blocks_.Add(success_block_);
135 blocks_.Add(backtrack_block_); 140 blocks_.Add(backtrack_block_);
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
247 Do(InstanceCall(InstanceCallDescriptor::FromToken(Token::kASSIGN_INDEX), 252 Do(InstanceCall(InstanceCallDescriptor::FromToken(Token::kASSIGN_INDEX),
248 matches_push, 253 matches_push,
249 index_push, 254 index_push,
250 value_push)); 255 value_push));
251 } 256 }
252 257
253 // Print the result if tracing. 258 // Print the result if tracing.
254 PRINT(PushLocal(result_)); 259 PRINT(PushLocal(result_));
255 260
256 // Return true on success. 261 // Return true on success.
257 AppendInstruction(new(I) ReturnInstr(kNoTokenPos, Bind(LoadLocal(result_)))); 262 AppendInstruction(new(I) ReturnInstr(kNoSourcePos, Bind(LoadLocal(result_))));
258 } 263 }
259 264
260 265
261 void IRRegExpMacroAssembler::GenerateExitBlock() { 266 void IRRegExpMacroAssembler::GenerateExitBlock() {
262 set_current_instruction(exit_block_); 267 set_current_instruction(exit_block_);
263 TAG(); 268 TAG();
264 269
265 // Return false on failure. 270 // Return false on failure.
266 AppendInstruction(new(I) ReturnInstr(kNoTokenPos, Bind(LoadLocal(result_)))); 271 AppendInstruction(new(I) ReturnInstr(kNoSourcePos, Bind(LoadLocal(result_))));
267 } 272 }
268 273
269 274
270 #if defined(TARGET_ARCH_ARM64) || \ 275 #if defined(TARGET_ARCH_ARM64) || \
271 defined(TARGET_ARCH_ARM) || \ 276 defined(TARGET_ARCH_ARM) || \
272 defined(TARGET_ARCH_MIPS) 277 defined(TARGET_ARCH_MIPS)
273 // Disabling unaligned accesses forces the regexp engine to load characters one 278 // Disabling unaligned accesses forces the regexp engine to load characters one
274 // by one instead of up to 4 at once, along with the associated performance hit. 279 // by one instead of up to 4 at once, along with the associated performance hit.
275 // TODO(zerny): Be less conservative about disabling unaligned accesses. 280 // TODO(zerny): Be less conservative about disabling unaligned accesses.
276 // For instance, ARMv6 supports unaligned accesses. Once it is enabled here, 281 // For instance, ARMv6 supports unaligned accesses. Once it is enabled here,
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
344 } 349 }
345 } 350 }
346 return Bool::True().raw(); 351 return Bool::True().raw();
347 } 352 }
348 353
349 354
350 LocalVariable* IRRegExpMacroAssembler::Parameter(const String& name, 355 LocalVariable* IRRegExpMacroAssembler::Parameter(const String& name,
351 intptr_t index) const { 356 intptr_t index) const {
352 const Type& local_type = Type::ZoneHandle(I, Type::DynamicType()); 357 const Type& local_type = Type::ZoneHandle(I, Type::DynamicType());
353 LocalVariable* local = 358 LocalVariable* local =
354 new(I) LocalVariable(kNoTokenPos, name, local_type); 359 new(I) LocalVariable(kNoSourcePos, name, local_type);
355 360
356 intptr_t param_frame_index = kParamEndSlotFromFp + kParamCount - index; 361 intptr_t param_frame_index = kParamEndSlotFromFp + kParamCount - index;
357 local->set_index(param_frame_index); 362 local->set_index(param_frame_index);
358 363
359 return local; 364 return local;
360 } 365 }
361 366
362 367
363 LocalVariable* IRRegExpMacroAssembler::Local(const String& name) { 368 LocalVariable* IRRegExpMacroAssembler::Local(const String& name) {
364 const Type& local_type = Type::ZoneHandle(I, Type::DynamicType()); 369 const Type& local_type = Type::ZoneHandle(I, Type::DynamicType());
365 LocalVariable* local = 370 LocalVariable* local =
366 new(I) LocalVariable(kNoTokenPos, name, local_type); 371 new(I) LocalVariable(kNoSourcePos, name, local_type);
367 local->set_index(GetNextLocalIndex()); 372 local->set_index(GetNextLocalIndex());
368 373
369 return local; 374 return local;
370 } 375 }
371 376
372 377
373 ConstantInstr* IRRegExpMacroAssembler::Int64Constant(int64_t value) const { 378 ConstantInstr* IRRegExpMacroAssembler::Int64Constant(int64_t value) const {
374 return new(I) ConstantInstr( 379 return new(I) ConstantInstr(
375 Integer::ZoneHandle(I, Integer::New(value, Heap::kOld))); 380 Integer::ZoneHandle(I, Integer::New(value, Heap::kOld)));
376 } 381 }
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
444 PushArgumentInstr* lhs_push = PushArgument(Bind(lhs)); 449 PushArgumentInstr* lhs_push = PushArgument(Bind(lhs));
445 PushArgumentInstr* rhs_push = PushArgument(Bind(rhs)); 450 PushArgumentInstr* rhs_push = PushArgument(Bind(rhs));
446 451
447 Value* lhs_value = 452 Value* lhs_value =
448 Bind(InstanceCall( 453 Bind(InstanceCall(
449 InstanceCallDescriptor::FromToken(intermediate_operator), 454 InstanceCallDescriptor::FromToken(intermediate_operator),
450 lhs_push, 455 lhs_push,
451 rhs_push)); 456 rhs_push));
452 Value* rhs_value = Bind(BoolConstant(true)); 457 Value* rhs_value = Bind(BoolConstant(true));
453 458
454 return new(I) StrictCompareInstr(kNoTokenPos, strict_comparison, 459 return new(I) StrictCompareInstr(kNoSourcePos, strict_comparison,
455 lhs_value, rhs_value, true); 460 lhs_value, rhs_value, true);
456 } 461 }
457 462
458 463
459 StaticCallInstr* IRRegExpMacroAssembler::StaticCall( 464 StaticCallInstr* IRRegExpMacroAssembler::StaticCall(
460 const Function& function) const { 465 const Function& function) const {
461 ZoneGrowableArray<PushArgumentInstr*>* arguments = 466 ZoneGrowableArray<PushArgumentInstr*>* arguments =
462 new(I) ZoneGrowableArray<PushArgumentInstr*>(0); 467 new(I) ZoneGrowableArray<PushArgumentInstr*>(0);
463 return StaticCall(function, arguments); 468 return StaticCall(function, arguments);
464 } 469 }
(...skipping 19 matching lines...) Expand all
484 arguments->Add(arg1); 489 arguments->Add(arg1);
485 arguments->Add(arg2); 490 arguments->Add(arg2);
486 491
487 return StaticCall(function, arguments); 492 return StaticCall(function, arguments);
488 } 493 }
489 494
490 495
491 StaticCallInstr* IRRegExpMacroAssembler::StaticCall( 496 StaticCallInstr* IRRegExpMacroAssembler::StaticCall(
492 const Function& function, 497 const Function& function,
493 ZoneGrowableArray<PushArgumentInstr*>* arguments) const { 498 ZoneGrowableArray<PushArgumentInstr*>* arguments) const {
494 return new(I) StaticCallInstr(kNoTokenPos, 499 return new(I) StaticCallInstr(kNoSourcePos,
495 function, 500 function,
496 Object::null_array(), 501 Object::null_array(),
497 arguments, 502 arguments,
498 ic_data_array_); 503 ic_data_array_);
499 } 504 }
500 505
501 506
502 InstanceCallInstr* IRRegExpMacroAssembler::InstanceCall( 507 InstanceCallInstr* IRRegExpMacroAssembler::InstanceCall(
503 const InstanceCallDescriptor& desc, 508 const InstanceCallDescriptor& desc,
504 PushArgumentInstr* arg1) const { 509 PushArgumentInstr* arg1) const {
(...skipping 30 matching lines...) Expand all
535 arguments->Add(arg3); 540 arguments->Add(arg3);
536 541
537 return InstanceCall(desc, arguments); 542 return InstanceCall(desc, arguments);
538 } 543 }
539 544
540 545
541 InstanceCallInstr* IRRegExpMacroAssembler::InstanceCall( 546 InstanceCallInstr* IRRegExpMacroAssembler::InstanceCall(
542 const InstanceCallDescriptor& desc, 547 const InstanceCallDescriptor& desc,
543 ZoneGrowableArray<PushArgumentInstr*> *arguments) const { 548 ZoneGrowableArray<PushArgumentInstr*> *arguments) const {
544 return 549 return
545 new(I) InstanceCallInstr(kNoTokenPos, 550 new(I) InstanceCallInstr(kNoSourcePos,
546 desc.name, 551 desc.name,
547 desc.token_kind, 552 desc.token_kind,
548 arguments, 553 arguments,
549 Object::null_array(), 554 Object::null_array(),
550 desc.checked_argument_count, 555 desc.checked_argument_count,
551 ic_data_array_); 556 ic_data_array_);
552 } 557 }
553 558
554 559
555 LoadLocalInstr* IRRegExpMacroAssembler::LoadLocal(LocalVariable* local) const { 560 LoadLocalInstr* IRRegExpMacroAssembler::LoadLocal(LocalVariable* local) const {
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
718 PushArgumentInstr* by_push = PushArgument(Bind(Int64Constant(by))); 723 PushArgumentInstr* by_push = PushArgument(Bind(Int64Constant(by)));
719 StoreLocal(position_register(reg), Bind(Add(reg_push, by_push))); 724 StoreLocal(position_register(reg), Bind(Add(reg_push, by_push)));
720 } 725 }
721 } 726 }
722 727
723 728
724 void IRRegExpMacroAssembler::Backtrack() { 729 void IRRegExpMacroAssembler::Backtrack() {
725 TAG(); 730 TAG();
726 CheckPreemption(); 731 CheckPreemption();
727 732
728 GrowableObjectArray& offsets = GrowableObjectArray::ZoneHandle( 733 const GrowableObjectArray& offsets = *entry_block_->indirect_entry_offsets();
729 I, GrowableObjectArray::New(Heap::kOld));
730 734
731 PushArgumentInstr* block_offsets_push = 735 PushArgumentInstr* block_offsets_push =
732 PushArgument(Bind(new(I) ConstantInstr(offsets))); 736 PushArgument(Bind(new(I) ConstantInstr(offsets)));
733 PushArgumentInstr* block_id_push = PushArgument(PopStack()); 737 PushArgumentInstr* block_id_push = PushArgument(PopStack());
734 738
735 Value* offset_value = 739 Value* offset_value =
736 Bind(InstanceCall(InstanceCallDescriptor::FromToken(Token::kINDEX), 740 Bind(InstanceCall(InstanceCallDescriptor::FromToken(Token::kINDEX),
737 block_offsets_push, 741 block_offsets_push,
738 block_id_push)); 742 block_id_push));
739 743
740 IndirectGotoInstr* igoto = new(I) IndirectGotoInstr(&offsets, offset_value); 744 IndirectGotoInstr* igoto = new(I) IndirectGotoInstr(offset_value);
741 CloseBlockWith(igoto); 745 CloseBlockWith(igoto);
742 igotos_.Add(igoto); 746 igotos_.Add(igoto);
743 } 747 }
744 748
745 749
746 // A BindBlock is analogous to assigning a label to a basic block. 750 // A BindBlock is analogous to assigning a label to a basic block.
747 // If the BlockLabel does not yet contain a block, it is created. 751 // If the BlockLabel does not yet contain a block, it is created.
748 // If there is a current instruction, append a goto to the bound block. 752 // If there is a current instruction, append a goto to the bound block.
749 void IRRegExpMacroAssembler::BindBlock(BlockLabel* label) { 753 void IRRegExpMacroAssembler::BindBlock(BlockLabel* label) {
750 ASSERT(!label->IsBound()); 754 ASSERT(!label->IsBound());
(...skipping 21 matching lines...) Expand all
772 LocalVariable* IRRegExpMacroAssembler::position_register(intptr_t index) { 776 LocalVariable* IRRegExpMacroAssembler::position_register(intptr_t index) {
773 // Create position registers as needed. 777 // Create position registers as needed.
774 for (intptr_t i = position_registers_.length(); i < index + 1; i++) { 778 for (intptr_t i = position_registers_.length(); i < index + 1; i++) {
775 position_registers_.Add(Local(Symbols::position_registers_())); 779 position_registers_.Add(Local(Symbols::position_registers_()));
776 } 780 }
777 781
778 return position_registers_[index]; 782 return position_registers_[index];
779 } 783 }
780 784
781 785
782 // TODO(zerny): Move the offset table outside to avoid having to keep 786 void IRRegExpMacroAssembler::FinalizeBlockOffsetTable(Isolate* isolate,
783 // the assembler around until after code generation; both function or regexp 787 GraphEntryInstr* graph) {
784 // would work. 788 const GrowableArray<IndirectEntryInstr*>& entries = graph->indirect_entries();
785 void IRRegExpMacroAssembler::FinalizeBlockOffsetTable() { 789 const intptr_t count = entries.length();
786 for (intptr_t i = 0; i < igotos_.length(); i++) { 790 GrowableObjectArray* offsets = graph->indirect_entry_offsets();
787 IndirectGotoInstr* igoto = igotos_[i]; 791 if (offsets->Capacity() < count) {
788 igoto->SetOffsetCount(I, indirect_id_.Count()); 792 offsets->Grow(count, Heap::kOld);
789 793 }
790 for (intptr_t j = 0; j < igoto->SuccessorCount(); j++) { 794 if (offsets->Length() < count) {
791 TargetEntryInstr* target = igoto->SuccessorAt(j); 795 offsets->SetLength(count);
792 796 }
793 // Optimizations might have modified the immediate target block, but 797 for (intptr_t i = 0; i < count; ++i) {
794 // it must end with a goto to the indirect entry. 798 IndirectEntryInstr* entry = entries[i];
795 Instruction* instr = target; 799 if (entry->offset() <= 0) {
796 while (instr != NULL && !instr->IsGoto()) { 800 // An invalid offset signifies an unreachable block.
797 instr = instr->next(); 801 // TODO(zerny): We should guard against usage of an invalid index.
798 } 802 continue;
799 ASSERT(instr->IsGoto());
800
801 IndirectEntryInstr* ientry =
802 instr->AsGoto()->successor()->AsIndirectEntry();
803 ASSERT(ientry != NULL);
804
805 // The intermediate block was possibly compacted, check both it and the
806 // final indirect entry for a valid offset. If neither are valid, then
807 // the indirect entry is unreachable.
808 intptr_t offset =
809 (target->offset() > 0) ? target->offset() : ientry->offset();
810 if (offset > 0) {
811 intptr_t adjusted_offset =
812 offset - Assembler::EntryPointToPcMarkerOffset();
813 igoto->SetOffsetAt(I, ientry->indirect_id(), adjusted_offset);
814 }
815 } 803 }
804 intptr_t offset = entry->offset() - Assembler::EntryPointToPcMarkerOffset();
805 offsets->SetAt(i, Smi::ZoneHandle(isolate, Smi::New(offset)));
816 } 806 }
817 } 807 }
818 808
809
819 void IRRegExpMacroAssembler::FinalizeIndirectGotos() { 810 void IRRegExpMacroAssembler::FinalizeIndirectGotos() {
820 for (intptr_t i = 0; i < igotos_.length(); i++) { 811 for (intptr_t i = 0; i < igotos_.length(); i++) {
821 for (intptr_t j = 0; j < entry_block_->indirect_entries().length(); j++) { 812 for (intptr_t j = 0; j < entry_block_->indirect_entries().length(); j++) {
822 igotos_.At(i)->AddSuccessor( 813 igotos_.At(i)->AddSuccessor(
823 TargetWithJoinGoto(entry_block_->indirect_entries().At(j))); 814 TargetWithJoinGoto(entry_block_->indirect_entries().At(j)));
824 } 815 }
825 } 816 }
826 } 817 }
827 818
828 819
(...skipping 938 matching lines...) Expand 10 before | Expand all | Expand 10 after
1767 blocks_.Add(target); 1758 blocks_.Add(target);
1768 1759
1769 target->AppendInstruction(new(I) GotoInstr(dst)); 1760 target->AppendInstruction(new(I) GotoInstr(dst));
1770 1761
1771 return target; 1762 return target;
1772 } 1763 }
1773 1764
1774 1765
1775 void IRRegExpMacroAssembler::CheckPreemption() { 1766 void IRRegExpMacroAssembler::CheckPreemption() {
1776 TAG(); 1767 TAG();
1777 AppendInstruction(new(I) CheckStackOverflowInstr(kNoTokenPos, 0)); 1768 AppendInstruction(new(I) CheckStackOverflowInstr(kNoSourcePos, 0));
1778 } 1769 }
1779 1770
1780 1771
1781 Definition* IRRegExpMacroAssembler::Add( 1772 Definition* IRRegExpMacroAssembler::Add(
1782 PushArgumentInstr* lhs, 1773 PushArgumentInstr* lhs,
1783 PushArgumentInstr* rhs) { 1774 PushArgumentInstr* rhs) {
1784 return InstanceCall(InstanceCallDescriptor::FromToken(Token::kADD), lhs, rhs); 1775 return InstanceCall(InstanceCallDescriptor::FromToken(Token::kADD), lhs, rhs);
1785 } 1776 }
1786 1777
1787 1778
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
1844 index, 1835 index,
1845 characters, 1836 characters,
1846 specialization_cid_, 1837 specialization_cid_,
1847 Scanner::kNoSourcePos)); 1838 Scanner::kNoSourcePos));
1848 } 1839 }
1849 1840
1850 1841
1851 #undef __ 1842 #undef __
1852 1843
1853 } // namespace dart 1844 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/regexp_assembler.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698