| Index: runtime/vm/intrinsifier_arm.cc
|
| diff --git a/runtime/vm/intrinsifier_arm.cc b/runtime/vm/intrinsifier_arm.cc
|
| index 8451fce293ddaa003f171926bb937b9381dc0441..82e2253bb3bafbfbdf7b50f2dd900017d409896e 100644
|
| --- a/runtime/vm/intrinsifier_arm.cc
|
| +++ b/runtime/vm/intrinsifier_arm.cc
|
| @@ -1599,6 +1599,94 @@ void Intrinsifier::TwoByteString_equality(Assembler* assembler) {
|
| }
|
|
|
|
|
| +static void GenerateRegexpSpecializationFor(
|
| + Assembler* assembler,
|
| + intptr_t cid,
|
| + Label* entry,
|
| + Label* exit) {
|
| + ASSERT(cid == kOneByteStringCid || cid == kTwoByteStringCid ||
|
| + cid == kExternalOneByteStringCid || cid == kExternalTwoByteStringCid);
|
| +
|
| + __ Bind(entry);
|
| +
|
| + // The passed string is of class cid.
|
| +
|
| + __ ldr(R0, FieldAddress(R2, JSRegExp::function_offset(cid)));
|
| +
|
| + // Set the subject if it is currently unset.
|
| +
|
| + __ LoadObject(R4, Object::null_object());
|
| + __ ldr(R5, FieldAddress(R2, JSRegExp::subject_offset(cid)));
|
| + __ cmp(R4, Operand(R5));
|
| + __ b(exit, NE);
|
| +
|
| + __ StoreIntoObject(R2,
|
| + FieldAddress(R2, JSRegExp::subject_offset(cid)),
|
| + R1,
|
| + false);
|
| +
|
| + __ b(exit);
|
| +}
|
| +
|
| +
|
| +void Intrinsifier::JSRegExp_ExecuteMatch(Assembler* assembler) {
|
| + Label is_one_byte_string;
|
| + Label is_two_byte_string;
|
| + Label is_external_one_byte_string;
|
| + Label is_external_two_byte_string;
|
| + Label fallthrough;
|
| +
|
| + static const intptr_t kRegExpParamOffset = + 2 * kWordSize;
|
| + static const intptr_t kStringParamOffset = + 1 * kWordSize;
|
| + // const Smi& start_index is located at (+ 0 * kWordSize).
|
| +
|
| + // Register assignments are as follows:
|
| + // R0: The appropriate (one- or two-byte specialized) matcher function.
|
| + // R2: The regexp object.
|
| + // R4: Temp.
|
| + // R5: Temp.
|
| + // R1: Temp, Pointer to the function's code which we then tail-call.
|
| +
|
| + __ ldr(R2, Address(SP, kRegExpParamOffset));
|
| + __ ldr(R1, Address(SP, kStringParamOffset));
|
| +
|
| + // Check if the string is a one byte string.
|
| +
|
| + __ CompareClassId(R1, kOneByteStringCid, R4);
|
| + __ b(&is_one_byte_string, EQ);
|
| +
|
| + __ CompareClassId(R1, kTwoByteStringCid, R4);
|
| + __ b(&is_two_byte_string, EQ);
|
| +
|
| + __ CompareClassId(R1, kExternalOneByteStringCid, R4);
|
| + __ b(&is_external_one_byte_string, EQ);
|
| +
|
| + __ CompareClassId(R1, kExternalTwoByteStringCid, R4);
|
| + __ b(&is_external_two_byte_string, EQ);
|
| +
|
| + GenerateRegexpSpecializationFor(assembler, kExternalTwoByteStringCid,
|
| + &is_external_two_byte_string, &fallthrough);
|
| + GenerateRegexpSpecializationFor(assembler, kExternalOneByteStringCid,
|
| + &is_external_one_byte_string, &fallthrough);
|
| + GenerateRegexpSpecializationFor(assembler, kTwoByteStringCid,
|
| + &is_two_byte_string, &fallthrough);
|
| + GenerateRegexpSpecializationFor(assembler, kOneByteStringCid,
|
| + &is_one_byte_string, &fallthrough);
|
| +
|
| + // R0 contains the appropriate (one- or two-byte string) function.
|
| +
|
| + __ Bind(&fallthrough);
|
| +
|
| + // Registers have been set up for the lazy compile stub at this point.
|
| + // It expects the function in R0 while; R5 and R4 are unused.
|
| +
|
| + // Tail-call the function.
|
| + __ ldr(R1, FieldAddress(R0, Function::instructions_offset()));
|
| + __ AddImmediate(R1, Instructions::HeaderSize() - kHeapObjectTag);
|
| + __ bx(R1);
|
| +}
|
| +
|
| +
|
| // On stack: user tag (+0).
|
| void Intrinsifier::UserTag_makeCurrent(Assembler* assembler) {
|
| // R1: Isolate.
|
|
|