| Index: runtime/vm/intrinsifier_x64.cc
|
| diff --git a/runtime/vm/intrinsifier_x64.cc b/runtime/vm/intrinsifier_x64.cc
|
| index 1d676548d807f6af31d294c2778f7652b399e088..3d399f3fc8a23de1b674ab162bfda9554eab2e21 100644
|
| --- a/runtime/vm/intrinsifier_x64.cc
|
| +++ b/runtime/vm/intrinsifier_x64.cc
|
| @@ -1510,6 +1510,95 @@ void Intrinsifier::TwoByteString_equality(Assembler* assembler) {
|
| }
|
|
|
|
|
| +static void GenerateRegexpSpecializationFor(
|
| + Assembler* assembler,
|
| + intptr_t cid,
|
| + Label* entry,
|
| + Label* exit,
|
| + bool jump_kind = Assembler::kFarJump) {
|
| + ASSERT(cid == kOneByteStringCid || cid == kTwoByteStringCid ||
|
| + cid == kExternalOneByteStringCid || cid == kExternalTwoByteStringCid);
|
| +
|
| + __ Bind(entry);
|
| +
|
| + // The passed string is of class cid.
|
| +
|
| + __ movq(RAX, FieldAddress(RBX, JSRegExp::function_offset(cid)));
|
| +
|
| + // Set the subject if it is currently unset.
|
| +
|
| + __ LoadObject(RCX, Object::null_object(), PP);
|
| + __ cmpq(RCX, FieldAddress(RBX, JSRegExp::subject_offset(cid)));
|
| + __ j(NOT_EQUAL, exit, jump_kind);
|
| +
|
| + __ StoreIntoObject(RBX,
|
| + FieldAddress(RBX, JSRegExp::subject_offset(cid)),
|
| + RDI,
|
| + false);
|
| +
|
| + __ jmp(exit, jump_kind);
|
| +}
|
| +
|
| +
|
| +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 = + 3 * kWordSize;
|
| + static const intptr_t kStringParamOffset = + 2 * kWordSize;
|
| + // const Smi& start_index is located at (+ 1 * kWordSize).
|
| +
|
| + // Register assignments are as follows:
|
| + // RAX: The appropriate (one- or two-byte specialized) matcher function.
|
| + // RBX: The regexp object.
|
| + // RCX: Temp.
|
| + // RDI: Temp, Pointer to the function's code which we then tail-call.
|
| +
|
| + __ movq(RBX, Address(RSP, kRegExpParamOffset));
|
| + __ movq(RDI, Address(RSP, kStringParamOffset));
|
| +
|
| + // Check if the string is a one byte string.
|
| +
|
| + __ CompareClassId(RDI, kOneByteStringCid);
|
| + __ j(EQUAL, &is_one_byte_string);
|
| +
|
| + __ CompareClassId(RDI, kTwoByteStringCid);
|
| + __ j(EQUAL, &is_two_byte_string);
|
| +
|
| + __ CompareClassId(RDI, kExternalOneByteStringCid);
|
| + __ j(EQUAL, &is_external_one_byte_string);
|
| +
|
| + __ CompareClassId(RDI, kExternalTwoByteStringCid);
|
| + __ j(EQUAL, &is_external_two_byte_string);
|
| +
|
| + 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,
|
| + Assembler::kNearJump);
|
| + GenerateRegexpSpecializationFor(assembler, kOneByteStringCid,
|
| + &is_one_byte_string, &fallthrough,
|
| + Assembler::kNearJump);
|
| +
|
| + // RAX 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 RAX while; R10 and RCX are unused.
|
| +
|
| + // Tail-call the function.
|
| + __ movq(RDI, FieldAddress(RAX, Function::instructions_offset()));
|
| + __ addq(RDI, Immediate(Instructions::HeaderSize() - kHeapObjectTag));
|
| + __ jmp(RDI);
|
| +}
|
| +
|
| +
|
| // On stack: user tag (+1), return-address (+0).
|
| void Intrinsifier::UserTag_makeCurrent(Assembler* assembler) {
|
| // RBX: Isolate.
|
|
|