Commit 5cc61896 authored by jgruber's avatar jgruber Committed by Commit bot

[regexp] Port RegExpExecStub to CSA (mostly)

This moves most of the logic contained in RegExpExecStub to CSA.  Benefits are
mostly easier readability and hackability, and removal of a large chunk of
platform-specific assembly.

Exit frame construction and the final call remain in RegExpExecStub.

BUG=v8:5339,v8:592

Review-Url: https://codereview.chromium.org/2738413002
Cr-Commit-Position: refs/heads/master@{#43844}
parent 9224d5d1
This diff is collapsed.
......@@ -54,11 +54,15 @@ const Register ApiGetterDescriptor::CallbackRegister() { return r3; }
const Register MathPowTaggedDescriptor::exponent() { return r2; }
const Register MathPowIntegerDescriptor::exponent() {
return MathPowTaggedDescriptor::exponent();
}
const Register RegExpExecDescriptor::StringRegister() { return r0; }
const Register RegExpExecDescriptor::LastIndexRegister() { return r1; }
const Register RegExpExecDescriptor::StringStartRegister() { return r2; }
const Register RegExpExecDescriptor::StringEndRegister() { return r3; }
const Register RegExpExecDescriptor::CodeRegister() { return r4; }
const Register GrowArrayElementsDescriptor::ObjectRegister() { return r0; }
const Register GrowArrayElementsDescriptor::KeyRegister() { return r3; }
......
This diff is collapsed.
......@@ -57,6 +57,11 @@ const Register MathPowTaggedDescriptor::exponent() { return x11; }
const Register MathPowIntegerDescriptor::exponent() { return x12; }
const Register RegExpExecDescriptor::StringRegister() { return x0; }
const Register RegExpExecDescriptor::LastIndexRegister() { return x1; }
const Register RegExpExecDescriptor::StringStartRegister() { return x2; }
const Register RegExpExecDescriptor::StringEndRegister() { return x3; }
const Register RegExpExecDescriptor::CodeRegister() { return x8; }
const Register GrowArrayElementsDescriptor::ObjectRegister() { return x0; }
const Register GrowArrayElementsDescriptor::KeyRegister() { return x3; }
......
......@@ -239,8 +239,7 @@ namespace internal {
V(kUnexpectedStringType, "Unexpected string type") \
V(kUnexpectedTestTypeofLiteralFlag, \
"Unexpected literal flag for TestTypeof bytecode") \
V(kUnexpectedTypeForRegExpDataFixedArrayExpected, \
"Unexpected type for RegExp data, FixedArray expected") \
V(kUnexpectedRegExpExecCall, "Unexpected call to the RegExpExecStub") \
V(kUnexpectedValue, "Unexpected value") \
V(kUnsupportedDoubleImmediate, "Unsupported double immediate") \
V(kUnsupportedLetCompoundAssignment, "Unsupported let compound assignment") \
......
This diff is collapsed.
......@@ -33,6 +33,18 @@ class RegExpBuiltinsAssembler : public CodeStubAssembler {
void StoreLastIndex(Node* context, Node* regexp, Node* value,
bool is_fastpath);
// Loads {var_string_start} and {var_string_end} with the corresponding
// offsets into the given {string}.
void GetStringPointers(Node* const string, Node* const offset,
Node* const last_index, Node* const string_length,
bool is_one_byte, Variable* var_string_start,
Variable* var_string_end);
// Low level logic around the actual call into generated Irregexp code.
Node* IrregexpExec(Node* const context, Node* const regexp,
Node* const string, Node* const last_index,
Node* const match_info);
Node* ConstructNewResultFromMatchInfo(Node* const context, Node* const regexp,
Node* const match_info,
Node* const string);
......
......@@ -2890,6 +2890,20 @@ Node* CodeStubAssembler::IsStringInstanceType(Node* instance_type) {
return Int32LessThan(instance_type, Int32Constant(FIRST_NONSTRING_TYPE));
}
Node* CodeStubAssembler::IsOneByteStringInstanceType(Node* instance_type) {
CSA_ASSERT(this, IsStringInstanceType(instance_type));
return Word32Equal(
Word32And(instance_type, Int32Constant(kStringEncodingMask)),
Int32Constant(kOneByteStringTag));
}
Node* CodeStubAssembler::IsSequentialStringInstanceType(Node* instance_type) {
CSA_ASSERT(this, IsStringInstanceType(instance_type));
return Word32Equal(
Word32And(instance_type, Int32Constant(kStringRepresentationMask)),
Int32Constant(kSeqStringTag));
}
Node* CodeStubAssembler::IsJSReceiverInstanceType(Node* instance_type) {
STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
return Int32GreaterThanOrEqual(instance_type,
......@@ -3255,18 +3269,16 @@ Node* AllocAndCopyStringCharacters(CodeStubAssembler* a, Node* context,
typedef CodeStubAssembler::Label Label;
typedef CodeStubAssembler::Variable Variable;
Label end(a), two_byte_sequential(a);
Label end(a), one_byte_sequential(a), two_byte_sequential(a);
Variable var_result(a, MachineRepresentation::kTagged);
Node* const smi_zero = a->SmiConstant(Smi::kZero);
STATIC_ASSERT((kOneByteStringTag & kStringEncodingMask) != 0);
a->GotoIf(a->Word32Equal(a->Word32And(from_instance_type,
a->Int32Constant(kStringEncodingMask)),
a->Int32Constant(0)),
&two_byte_sequential);
a->Branch(a->IsOneByteStringInstanceType(from_instance_type),
&one_byte_sequential, &two_byte_sequential);
// The subject string is a sequential one-byte string.
a->Bind(&one_byte_sequential);
{
Node* result =
a->AllocateSeqOneByteString(context, a->SmiToWord(character_count));
......@@ -3551,6 +3563,109 @@ Node* IsShortExternalStringInstanceType(CodeStubAssembler* a,
} // namespace
void CodeStubAssembler::TryUnpackString(Variable* var_string,
Variable* var_offset,
Variable* var_instance_type,
Label* if_bailout) {
DCHECK_EQ(var_string->rep(), MachineType::PointerRepresentation());
DCHECK_EQ(var_offset->rep(), MachineType::PointerRepresentation());
DCHECK_EQ(var_instance_type->rep(), MachineRepresentation::kWord32);
CSA_ASSERT(this, IsString(var_string->value()));
Label out(this);
VariableList vars({var_string, var_offset, var_instance_type}, zone());
Label dispatch(this, vars);
Label if_isdirect(this);
Label if_iscons(this, Label::kDeferred);
Label if_isexternal(this, Label::kDeferred);
Label if_issliced(this, Label::kDeferred);
Label if_isthin(this, Label::kDeferred);
Goto(&dispatch);
// Dispatch based on string representation.
Bind(&dispatch);
{
int32_t values[] = {
kSeqStringTag, kConsStringTag, kExternalStringTag,
kSlicedStringTag, kThinStringTag,
};
Label* labels[] = {
&if_isdirect, &if_iscons, &if_isexternal, &if_issliced, &if_isthin,
};
STATIC_ASSERT(arraysize(values) == arraysize(labels));
Node* const representation = Word32And(
var_instance_type->value(), Int32Constant(kStringRepresentationMask));
Switch(representation, if_bailout, values, labels, arraysize(values));
}
// Cons string. Check whether it is flat, then fetch first part.
// Flat cons strings have an empty second part.
Bind(&if_iscons);
{
Node* const string = var_string->value();
GotoIfNot(IsEmptyString(LoadObjectField(string, ConsString::kSecondOffset)),
if_bailout);
Node* const lhs = LoadObjectField(string, ConsString::kFirstOffset);
var_string->Bind(BitcastTaggedToWord(lhs));
var_instance_type->Bind(LoadInstanceType(lhs));
Goto(&dispatch);
}
// Sliced string. Fetch parent and correct start index by offset.
Bind(&if_issliced);
{
Node* const string = var_string->value();
Node* const sliced_offset =
LoadObjectField(string, SlicedString::kOffsetOffset);
var_offset->Bind(IntPtrAdd(var_offset->value(), SmiUntag(sliced_offset)));
Node* const parent = LoadObjectField(string, SlicedString::kParentOffset);
var_string->Bind(BitcastTaggedToWord(parent));
var_instance_type->Bind(LoadInstanceType(parent));
Goto(&dispatch);
}
// Thin string. Fetch the actual string.
Bind(&if_isthin);
{
Node* const string = var_string->value();
Node* const actual_string =
LoadObjectField(string, ThinString::kActualOffset);
Node* const actual_instance_type = LoadInstanceType(actual_string);
var_string->Bind(BitcastTaggedToWord(actual_string));
var_instance_type->Bind(actual_instance_type);
Goto(&dispatch);
}
// External string.
Bind(&if_isexternal);
{
Node* const string = var_string->value();
Node* const faked_seq_string =
TryDerefExternalString(string, var_instance_type->value(), if_bailout);
STATIC_ASSERT(kSeqStringTag == 0x0);
Node* const faked_seq_instance_type = Word32Xor(
var_instance_type->value(), Int32Constant(kExternalStringTag));
CSA_ASSERT(this, IsSequentialStringInstanceType(faked_seq_instance_type));
var_string->Bind(faked_seq_string);
var_instance_type->Bind(faked_seq_instance_type);
Goto(&if_isdirect);
}
Bind(&if_isdirect);
}
Node* CodeStubAssembler::TryDerefExternalString(Node* const string,
Node* const instance_type,
Label* if_bailout) {
......@@ -5618,23 +5733,10 @@ void CodeStubAssembler::UpdateFeedback(Node* feedback, Node* feedback_vector,
}
Node* CodeStubAssembler::LoadReceiverMap(Node* receiver) {
Variable var_receiver_map(this, MachineRepresentation::kTagged);
Label load_smi_map(this, Label::kDeferred), load_receiver_map(this),
if_result(this);
Branch(TaggedIsSmi(receiver), &load_smi_map, &load_receiver_map);
Bind(&load_smi_map);
{
var_receiver_map.Bind(LoadRoot(Heap::kHeapNumberMapRootIndex));
Goto(&if_result);
}
Bind(&load_receiver_map);
{
var_receiver_map.Bind(LoadMap(receiver));
Goto(&if_result);
}
Bind(&if_result);
return var_receiver_map.value();
return Select(TaggedIsSmi(receiver),
[=] { return LoadRoot(Heap::kHeapNumberMapRootIndex); },
[=] { return LoadMap(receiver); },
MachineRepresentation::kTagged);
}
Node* CodeStubAssembler::TryToIntptr(Node* key, Label* miss) {
......
......@@ -691,6 +691,8 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
Node* IsSpecialReceiverMap(Node* map);
Node* IsSpecialReceiverInstanceType(Node* instance_type);
Node* IsStringInstanceType(Node* instance_type);
Node* IsOneByteStringInstanceType(Node* instance_type);
Node* IsSequentialStringInstanceType(Node* instance_type);
Node* IsString(Node* object);
Node* IsJSObject(Node* object);
Node* IsJSGlobalProxy(Node* object);
......@@ -736,6 +738,14 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
Node* StringAdd(Node* context, Node* first, Node* second,
AllocationFlags flags = kNone);
// Tries to unpack |string| into a pseudo-sequential string. For instance,
// In addition to the work done by TryDerefExternalString and
// MaybeDerefIndirectString, this method can also unpack sliced strings into
// a (string, offset) pair. The same GC restrictions on the returned string
// value apply as for TryDerefExternalString.
void TryUnpackString(Variable* var_string, Variable* var_offset,
Variable* var_instance_type, Label* if_bailout);
// Unpack the external string, returning a pointer that (offset-wise) looks
// like a sequential string.
// Note that this pointer is not tagged and does not point to a real
......
This diff is collapsed.
......@@ -52,11 +52,15 @@ const Register ApiGetterDescriptor::CallbackRegister() { return eax; }
const Register MathPowTaggedDescriptor::exponent() { return eax; }
const Register MathPowIntegerDescriptor::exponent() {
return MathPowTaggedDescriptor::exponent();
}
const Register RegExpExecDescriptor::StringRegister() { return eax; }
const Register RegExpExecDescriptor::LastIndexRegister() { return ecx; }
const Register RegExpExecDescriptor::StringStartRegister() { return edx; }
const Register RegExpExecDescriptor::StringEndRegister() { return ebx; }
const Register RegExpExecDescriptor::CodeRegister() { return edi; }
const Register GrowArrayElementsDescriptor::ObjectRegister() { return eax; }
const Register GrowArrayElementsDescriptor::KeyRegister() { return ebx; }
......
......@@ -492,6 +492,24 @@ void CallICTrampolineDescriptor::InitializePlatformIndependent(
machine_types);
}
void RegExpExecDescriptor::InitializePlatformIndependent(
CallInterfaceDescriptorData* data) {
// kString, kLastIndex, kStringStart, kStringEnd, kEntryPoint
MachineType machine_types[] = {MachineType::AnyTagged(), MachineType::Int32(),
MachineType::Pointer(), MachineType::Pointer(),
MachineType::AnyTagged()};
data->InitializePlatformIndependent(arraysize(machine_types), 0,
machine_types);
}
void RegExpExecDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {StringRegister(), LastIndexRegister(),
StringStartRegister(), StringEndRegister(),
CodeRegister()};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void BuiltinDescriptor::InitializePlatformIndependent(
CallInterfaceDescriptorData* data) {
// kTarget, kNewTarget, kArgumentsCount
......
......@@ -647,9 +647,15 @@ class CallConstructDescriptor : public CallInterfaceDescriptor {
class RegExpExecDescriptor : public CallInterfaceDescriptor {
public:
DEFINE_PARAMETERS(kRegExpObject, kString, kPreviousIndex, kLastMatchInfo)
DECLARE_DESCRIPTOR_WITH_STACK_ARGS(RegExpExecDescriptor,
CallInterfaceDescriptor)
DEFINE_PARAMETERS(kString, kLastIndex, kStringStart, kStringEnd, kCode)
DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(RegExpExecDescriptor,
CallInterfaceDescriptor)
static const Register StringRegister();
static const Register LastIndexRegister();
static const Register StringStartRegister();
static const Register StringEndRegister();
static const Register CodeRegister();
};
class RegExpReplaceDescriptor : public CallInterfaceDescriptor {
......
This diff is collapsed.
......@@ -52,11 +52,15 @@ const Register ApiGetterDescriptor::CallbackRegister() { return a3; }
const Register MathPowTaggedDescriptor::exponent() { return a2; }
const Register MathPowIntegerDescriptor::exponent() {
return MathPowTaggedDescriptor::exponent();
}
const Register RegExpExecDescriptor::StringRegister() { return a0; }
const Register RegExpExecDescriptor::LastIndexRegister() { return a1; }
const Register RegExpExecDescriptor::StringStartRegister() { return a2; }
const Register RegExpExecDescriptor::StringEndRegister() { return a3; }
const Register RegExpExecDescriptor::CodeRegister() { return t0; }
const Register GrowArrayElementsDescriptor::ObjectRegister() { return a0; }
const Register GrowArrayElementsDescriptor::KeyRegister() { return a3; }
......
This diff is collapsed.
......@@ -52,11 +52,15 @@ const Register ApiGetterDescriptor::CallbackRegister() { return a3; }
const Register MathPowTaggedDescriptor::exponent() { return a2; }
const Register MathPowIntegerDescriptor::exponent() {
return MathPowTaggedDescriptor::exponent();
}
const Register RegExpExecDescriptor::StringRegister() { return a0; }
const Register RegExpExecDescriptor::LastIndexRegister() { return a1; }
const Register RegExpExecDescriptor::StringStartRegister() { return a2; }
const Register RegExpExecDescriptor::StringEndRegister() { return a3; }
const Register RegExpExecDescriptor::CodeRegister() { return t0; }
const Register GrowArrayElementsDescriptor::ObjectRegister() { return a0; }
const Register GrowArrayElementsDescriptor::KeyRegister() { return a3; }
......
......@@ -8593,16 +8593,6 @@ class JSRegExp: public JSObject {
static const int kIrregexpDataSize = kIrregexpCaptureNameMapIndex + 1;
// Offsets directly into the data fixed array.
static const int kDataTagOffset =
FixedArray::kHeaderSize + kTagIndex * kPointerSize;
static const int kDataOneByteCodeOffset =
FixedArray::kHeaderSize + kIrregexpLatin1CodeIndex * kPointerSize;
static const int kDataUC16CodeOffset =
FixedArray::kHeaderSize + kIrregexpUC16CodeIndex * kPointerSize;
static const int kIrregexpCaptureCountOffset =
FixedArray::kHeaderSize + kIrregexpCaptureCountIndex * kPointerSize;
// In-object fields.
static const int kLastIndexFieldIndex = 0;
static const int kInObjectFieldCount = 1;
......
This diff is collapsed.
......@@ -52,11 +52,15 @@ const Register ApiGetterDescriptor::CallbackRegister() { return r6; }
const Register MathPowTaggedDescriptor::exponent() { return r5; }
const Register MathPowIntegerDescriptor::exponent() {
return MathPowTaggedDescriptor::exponent();
}
const Register RegExpExecDescriptor::StringRegister() { return r3; }
const Register RegExpExecDescriptor::LastIndexRegister() { return r4; }
const Register RegExpExecDescriptor::StringStartRegister() { return r5; }
const Register RegExpExecDescriptor::StringEndRegister() { return r6; }
const Register RegExpExecDescriptor::CodeRegister() { return r17; }
const Register GrowArrayElementsDescriptor::ObjectRegister() { return r3; }
const Register GrowArrayElementsDescriptor::KeyRegister() { return r6; }
......
......@@ -1655,7 +1655,7 @@ RUNTIME_FUNCTION(Runtime_RegExpReplace) {
RUNTIME_FUNCTION(Runtime_RegExpExecReThrow) {
SealHandleScope shs(isolate);
DCHECK_EQ(4, args.length());
DCHECK_EQ(0, args.length());
Object* exception = isolate->pending_exception();
isolate->clear_pending_exception();
return isolate->ReThrow(exception);
......
......@@ -471,7 +471,7 @@ namespace internal {
F(RegExpCreate, 1, 1) \
F(RegExpExec, 4, 1) \
F(RegExpExecMultiple, 4, 1) \
F(RegExpExecReThrow, 4, 1) \
F(RegExpExecReThrow, 0, 1) \
F(RegExpInitializeAndCompile, 3, 1) \
F(RegExpInternalReplace, 3, 1) \
F(RegExpReplace, 3, 1) \
......
This diff is collapsed.
......@@ -56,6 +56,12 @@ const Register MathPowIntegerDescriptor::exponent() {
return MathPowTaggedDescriptor::exponent();
}
const Register RegExpExecDescriptor::StringRegister() { return r2; }
const Register RegExpExecDescriptor::LastIndexRegister() { return r3; }
const Register RegExpExecDescriptor::StringStartRegister() { return r4; }
const Register RegExpExecDescriptor::StringEndRegister() { return r5; }
const Register RegExpExecDescriptor::CodeRegister() { return r9; }
const Register GrowArrayElementsDescriptor::ObjectRegister() { return r2; }
const Register GrowArrayElementsDescriptor::KeyRegister() { return r5; }
......
This diff is collapsed.
......@@ -52,11 +52,15 @@ const Register ApiGetterDescriptor::CallbackRegister() { return rbx; }
const Register MathPowTaggedDescriptor::exponent() { return rdx; }
const Register MathPowIntegerDescriptor::exponent() {
return MathPowTaggedDescriptor::exponent();
}
const Register RegExpExecDescriptor::StringRegister() { return arg_reg_1; }
const Register RegExpExecDescriptor::LastIndexRegister() { return r11; }
const Register RegExpExecDescriptor::StringStartRegister() { return arg_reg_3; }
const Register RegExpExecDescriptor::StringEndRegister() { return arg_reg_4; }
const Register RegExpExecDescriptor::CodeRegister() { return rax; }
const Register GrowArrayElementsDescriptor::ObjectRegister() { return rax; }
const Register GrowArrayElementsDescriptor::KeyRegister() { return rbx; }
......
This diff is collapsed.
......@@ -52,11 +52,15 @@ const Register ApiGetterDescriptor::CallbackRegister() { return eax; }
const Register MathPowTaggedDescriptor::exponent() { return eax; }
const Register MathPowIntegerDescriptor::exponent() {
return MathPowTaggedDescriptor::exponent();
}
const Register RegExpExecDescriptor::StringRegister() { return eax; }
const Register RegExpExecDescriptor::LastIndexRegister() { return ecx; }
const Register RegExpExecDescriptor::StringStartRegister() { return edx; }
const Register RegExpExecDescriptor::StringEndRegister() { return ebx; }
const Register RegExpExecDescriptor::CodeRegister() { return edi; }
const Register GrowArrayElementsDescriptor::ObjectRegister() { return eax; }
const Register GrowArrayElementsDescriptor::KeyRegister() { return ebx; }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment