| Index: runtime/vm/regexp_assembler.cc
|
| diff --git a/runtime/vm/regexp_assembler.cc b/runtime/vm/regexp_assembler.cc
|
| index fa666ae3e55f77a89a0fefa3d1117b628693ded0..ac8f360ec1cff8403890386caef2839d2266155d 100644
|
| --- a/runtime/vm/regexp_assembler.cc
|
| +++ b/runtime/vm/regexp_assembler.cc
|
| @@ -158,6 +158,7 @@ void IRRegExpMacroAssembler::InitializeLocals() {
|
| match_end_index_ = Local(Symbols::match_end_index());
|
| char_in_capture_ = Local(Symbols::char_in_capture());
|
| char_in_match_ = Local(Symbols::char_in_match());
|
| + index_temp_ = Local(Symbols::index_temp());
|
| result_ = Local(Symbols::result());
|
|
|
| string_param_ = Parameter(Symbols::string_param(), 0);
|
| @@ -944,8 +945,8 @@ void IRRegExpMacroAssembler::CheckNotBackReferenceIgnoreCase(
|
| BlockLabel loop;
|
| BindBlock(&loop);
|
|
|
| - StoreLocal(char_in_capture_, CharacterAt(LoadLocal(capture_start_index_)));
|
| - StoreLocal(char_in_match_, CharacterAt(LoadLocal(match_start_index_)));
|
| + StoreLocal(char_in_capture_, CharacterAt(capture_start_index_));
|
| + StoreLocal(char_in_match_, CharacterAt(match_start_index_));
|
|
|
| BranchOrBacktrack(Comparison(kEQ,
|
| LoadLocal(char_in_capture_),
|
| @@ -1105,8 +1106,8 @@ void IRRegExpMacroAssembler::CheckNotBackReference(
|
| BlockLabel loop;
|
| BindBlock(&loop);
|
|
|
| - StoreLocal(char_in_capture_, CharacterAt(LoadLocal(capture_start_index_)));
|
| - StoreLocal(char_in_match_, CharacterAt(LoadLocal(match_start_index_)));
|
| + StoreLocal(char_in_capture_, CharacterAt(capture_start_index_));
|
| + StoreLocal(char_in_match_, CharacterAt(match_start_index_));
|
|
|
| BranchOrBacktrack(Comparison(kNE,
|
| LoadLocal(char_in_capture_),
|
| @@ -1765,9 +1766,6 @@ void IRRegExpMacroAssembler::LoadCurrentCharacterUnchecked(
|
| ASSERT(characters == 1 || characters == 2);
|
| }
|
|
|
| - // Bind the pattern as the load receiver.
|
| - Value* pattern = BindLoadLocal(*string_param_);
|
| -
|
| // Calculate the addressed string index as:
|
| // cp_offset + current_position_ + string_param_length_
|
| // TODO(zerny): Avoid generating 'add' instance-calls here.
|
| @@ -1779,30 +1777,53 @@ void IRRegExpMacroAssembler::LoadCurrentCharacterUnchecked(
|
| PushArgument(Bind(Add(off_arg, pos_arg)));
|
| PushArgumentInstr* len_arg =
|
| PushArgument(BindLoadLocal(*string_param_length_));
|
| - Value* index = Bind(Add(off_pos_arg, len_arg));
|
| + // Index is stored in a temporary local so that we can later load it safely.
|
| + StoreLocal(index_temp_, Bind(Add(off_pos_arg, len_arg)));
|
|
|
| // Load and store the code units.
|
| - Value* code_unit_value = LoadCodeUnitsAt(pattern, index, characters);
|
| + Value* code_unit_value = LoadCodeUnitsAt(index_temp_, characters);
|
| StoreLocal(current_character_, code_unit_value);
|
| PRINT(PushLocal(current_character_));
|
| }
|
|
|
|
|
| -Value* IRRegExpMacroAssembler::CharacterAt(Definition* index) {
|
| - Value* pattern_val = BindLoadLocal(*string_param_);
|
| - Value* index_val = Bind(index);
|
| - return LoadCodeUnitsAt(pattern_val, index_val, 1);
|
| +Value* IRRegExpMacroAssembler::CharacterAt(LocalVariable* index) {
|
| + return LoadCodeUnitsAt(index, 1);
|
| }
|
|
|
|
|
| -// Note: We can't replace pattern with a load-local of string_param_
|
| -// because we need to maintain the stack discipline in unoptimized code.
|
| -Value* IRRegExpMacroAssembler::LoadCodeUnitsAt(Value* pattern,
|
| - Value* index,
|
| +Value* IRRegExpMacroAssembler::LoadCodeUnitsAt(LocalVariable* index,
|
| intptr_t characters) {
|
| + // Bind the pattern as the load receiver.
|
| + Value* pattern_val = BindLoadLocal(*string_param_);
|
| + if (RawObject::IsExternalStringClassId(specialization_cid_)) {
|
| + // The data of an external string is stored through two indirections.
|
| + intptr_t external_offset;
|
| + intptr_t data_offset;
|
| + if (specialization_cid_ == kExternalOneByteStringCid) {
|
| + external_offset = ExternalOneByteString::external_data_offset();
|
| + data_offset = RawExternalOneByteString::ExternalData::data_offset();
|
| + } else if (specialization_cid_ == kExternalTwoByteStringCid) {
|
| + external_offset = ExternalTwoByteString::external_data_offset();
|
| + data_offset = RawExternalTwoByteString::ExternalData::data_offset();
|
| + } else {
|
| + UNREACHABLE();
|
| + }
|
| + // This pushes untagged values on the stack which are immediately consumed:
|
| + // the first value is consumed to obtain the second value which is consumed
|
| + // by LoadCodeUnitsAtInstr below.
|
| + Value* external_val =
|
| + Bind(new(I) LoadUntaggedInstr(pattern_val, external_offset));
|
| + pattern_val =
|
| + Bind(new(I) LoadUntaggedInstr(external_val, data_offset));
|
| + }
|
| +
|
| + // Here pattern_val might be untagged so this must not trigger a GC.
|
| + Value* index_val = BindLoadLocal(*index);
|
| +
|
| return Bind(new(I) LoadCodeUnitsInstr(
|
| - pattern,
|
| - index,
|
| + pattern_val,
|
| + index_val,
|
| characters,
|
| specialization_cid_,
|
| Scanner::kNoSourcePos));
|
|
|