Index: src/builtins/builtins-regexp.cc |
diff --git a/src/builtins/builtins-regexp.cc b/src/builtins/builtins-regexp.cc |
index ba8b692fbced8a67bdb47f29858df5f5407440c3..2ad9c4f18898f165ea046ecda3c4c91b0d86bce4 100644 |
--- a/src/builtins/builtins-regexp.cc |
+++ b/src/builtins/builtins-regexp.cc |
@@ -14,138 +14,194 @@ namespace v8 { |
namespace internal { |
typedef compiler::Node Node; |
-typedef CodeStubAssembler::Label CLabel; |
-typedef CodeStubAssembler::Variable CVariable; |
typedef CodeStubAssembler::ParameterMode ParameterMode; |
typedef compiler::CodeAssemblerState CodeAssemblerState; |
class RegExpBuiltinsAssembler : public CodeStubAssembler { |
public: |
- explicit RegExpBuiltinsAssembler(compiler::CodeAssemblerState* state) |
+ explicit RegExpBuiltinsAssembler(CodeAssemblerState* state) |
: CodeStubAssembler(state) {} |
protected: |
+ Node* FastLoadLastIndex(Node* regexp); |
+ Node* SlowLoadLastIndex(Node* context, Node* regexp); |
+ Node* LoadLastIndex(Node* context, Node* regexp, bool is_fastpath); |
+ |
+ void FastStoreLastIndex(Node* regexp, Node* value); |
+ void SlowStoreLastIndex(Node* context, Node* regexp, Node* value); |
+ void StoreLastIndex(Node* context, Node* regexp, Node* value, |
+ bool is_fastpath); |
+ |
+ Node* ConstructNewResultFromMatchInfo(Node* context, Node* match_info, |
+ Node* string); |
+ |
+ Node* RegExpPrototypeExecBodyWithoutResult(Node* const context, |
+ Node* const regexp, |
+ Node* const string, |
+ Label* if_didnotmatch, |
+ const bool is_fastpath); |
+ Node* RegExpPrototypeExecBody(Node* const context, Node* const regexp, |
+ Node* const string, const bool is_fastpath); |
+ |
+ Node* ThrowIfNotJSReceiver(Node* context, Node* maybe_receiver, |
+ MessageTemplate::Template msg_template, |
+ char const* method_name); |
+ |
+ Node* IsInitialRegExpMap(Node* context, Node* map); |
+ void BranchIfFastRegExp(Node* context, Node* map, Label* if_isunmodified, |
+ Label* if_ismodified); |
+ void BranchIfFastRegExpResult(Node* context, Node* map, |
+ Label* if_isunmodified, Label* if_ismodified); |
+ |
+ Node* FlagsGetter(Node* const context, Node* const regexp, bool is_fastpath); |
+ |
+ Node* FastFlagGetter(Node* const regexp, JSRegExp::Flag flag); |
+ Node* SlowFlagGetter(Node* const context, Node* const regexp, |
+ JSRegExp::Flag flag); |
+ Node* FlagGetter(Node* const context, Node* const regexp, JSRegExp::Flag flag, |
+ bool is_fastpath); |
+ void FlagGetter(JSRegExp::Flag flag, v8::Isolate::UseCounterFeature counter, |
+ const char* method_name); |
+ |
+ Node* IsRegExp(Node* const context, Node* const maybe_receiver); |
+ Node* RegExpInitialize(Node* const context, Node* const regexp, |
+ Node* const maybe_pattern, Node* const maybe_flags); |
+ |
+ Node* RegExpExec(Node* context, Node* regexp, Node* string); |
+ |
+ Node* AdvanceStringIndex(Node* const string, Node* const index, |
+ Node* const is_unicode); |
+ |
+ void RegExpPrototypeMatchBody(Node* const context, Node* const regexp, |
+ Node* const string, const bool is_fastpath); |
+ |
+ void RegExpPrototypeSearchBodyFast(Node* const context, Node* const regexp, |
+ Node* const string); |
+ void RegExpPrototypeSearchBodySlow(Node* const context, Node* const regexp, |
+ Node* const string); |
+ |
+ void RegExpPrototypeSplitBody(Node* const context, Node* const regexp, |
+ Node* const string, Node* const limit); |
+ |
+ Node* ReplaceGlobalCallableFastPath(Node* context, Node* regexp, Node* string, |
+ Node* replace_callable); |
+ Node* ReplaceSimpleStringFastPath(Node* context, Node* regexp, Node* string, |
+ Node* replace_string); |
}; |
// ----------------------------------------------------------------------------- |
// ES6 section 21.2 RegExp Objects |
-namespace { |
- |
-Node* FastLoadLastIndex(CodeStubAssembler* a, Node* regexp) { |
+Node* RegExpBuiltinsAssembler::FastLoadLastIndex(Node* regexp) { |
// Load the in-object field. |
static const int field_offset = |
JSRegExp::kSize + JSRegExp::kLastIndexFieldIndex * kPointerSize; |
- return a->LoadObjectField(regexp, field_offset); |
+ return LoadObjectField(regexp, field_offset); |
} |
-Node* SlowLoadLastIndex(CodeStubAssembler* a, Node* context, Node* regexp) { |
+Node* RegExpBuiltinsAssembler::SlowLoadLastIndex(Node* context, Node* regexp) { |
// Load through the GetProperty stub. |
- Node* const name = |
- a->HeapConstant(a->isolate()->factory()->lastIndex_string()); |
- Callable getproperty_callable = CodeFactory::GetProperty(a->isolate()); |
- return a->CallStub(getproperty_callable, context, regexp, name); |
+ Node* const name = HeapConstant(isolate()->factory()->lastIndex_string()); |
+ Callable getproperty_callable = CodeFactory::GetProperty(isolate()); |
+ return CallStub(getproperty_callable, context, regexp, name); |
} |
-Node* LoadLastIndex(CodeStubAssembler* a, Node* context, Node* regexp, |
- bool is_fastpath) { |
- return is_fastpath ? FastLoadLastIndex(a, regexp) |
- : SlowLoadLastIndex(a, context, regexp); |
+Node* RegExpBuiltinsAssembler::LoadLastIndex(Node* context, Node* regexp, |
+ bool is_fastpath) { |
+ return is_fastpath ? FastLoadLastIndex(regexp) |
+ : SlowLoadLastIndex(context, regexp); |
} |
// The fast-path of StoreLastIndex when regexp is guaranteed to be an unmodified |
// JSRegExp instance. |
-void FastStoreLastIndex(CodeStubAssembler* a, Node* regexp, Node* value) { |
+void RegExpBuiltinsAssembler::FastStoreLastIndex(Node* regexp, Node* value) { |
// Store the in-object field. |
static const int field_offset = |
JSRegExp::kSize + JSRegExp::kLastIndexFieldIndex * kPointerSize; |
- a->StoreObjectField(regexp, field_offset, value); |
+ StoreObjectField(regexp, field_offset, value); |
} |
-void SlowStoreLastIndex(CodeStubAssembler* a, Node* context, Node* regexp, |
- Node* value) { |
+void RegExpBuiltinsAssembler::SlowStoreLastIndex(Node* context, Node* regexp, |
+ Node* value) { |
// Store through runtime. |
// TODO(ishell): Use SetPropertyStub here once available. |
- Node* const name = |
- a->HeapConstant(a->isolate()->factory()->lastIndex_string()); |
- Node* const language_mode = a->SmiConstant(Smi::FromInt(STRICT)); |
- a->CallRuntime(Runtime::kSetProperty, context, regexp, name, value, |
- language_mode); |
+ Node* const name = HeapConstant(isolate()->factory()->lastIndex_string()); |
+ Node* const language_mode = SmiConstant(Smi::FromInt(STRICT)); |
+ CallRuntime(Runtime::kSetProperty, context, regexp, name, value, |
+ language_mode); |
} |
-void StoreLastIndex(CodeStubAssembler* a, Node* context, Node* regexp, |
- Node* value, bool is_fastpath) { |
+void RegExpBuiltinsAssembler::StoreLastIndex(Node* context, Node* regexp, |
+ Node* value, bool is_fastpath) { |
if (is_fastpath) { |
- FastStoreLastIndex(a, regexp, value); |
+ FastStoreLastIndex(regexp, value); |
} else { |
- SlowStoreLastIndex(a, context, regexp, value); |
+ SlowStoreLastIndex(context, regexp, value); |
} |
} |
-Node* ConstructNewResultFromMatchInfo(Isolate* isolate, CodeStubAssembler* a, |
- Node* context, Node* match_info, |
- Node* string) { |
- CLabel out(a); |
+Node* RegExpBuiltinsAssembler::ConstructNewResultFromMatchInfo(Node* context, |
+ Node* match_info, |
+ Node* string) { |
+ Label out(this); |
- Node* const num_indices = a->SmiUntag(a->LoadFixedArrayElement( |
+ Node* const num_indices = SmiUntag(LoadFixedArrayElement( |
match_info, RegExpMatchInfo::kNumberOfCapturesIndex)); |
- Node* const num_results = a->SmiTag(a->WordShr(num_indices, 1)); |
+ Node* const num_results = SmiTag(WordShr(num_indices, 1)); |
Node* const start = |
- a->LoadFixedArrayElement(match_info, RegExpMatchInfo::kFirstCaptureIndex); |
- Node* const end = a->LoadFixedArrayElement( |
+ LoadFixedArrayElement(match_info, RegExpMatchInfo::kFirstCaptureIndex); |
+ Node* const end = LoadFixedArrayElement( |
match_info, RegExpMatchInfo::kFirstCaptureIndex + 1); |
// Calculate the substring of the first match before creating the result array |
// to avoid an unnecessary write barrier storing the first result. |
- Node* const first = a->SubString(context, string, start, end); |
+ Node* const first = SubString(context, string, start, end); |
Node* const result = |
- a->AllocateRegExpResult(context, num_results, start, string); |
- Node* const result_elements = a->LoadElements(result); |
+ AllocateRegExpResult(context, num_results, start, string); |
+ Node* const result_elements = LoadElements(result); |
- a->StoreFixedArrayElement(result_elements, 0, first, SKIP_WRITE_BARRIER); |
+ StoreFixedArrayElement(result_elements, 0, first, SKIP_WRITE_BARRIER); |
- a->GotoIf(a->SmiEqual(num_results, a->SmiConstant(Smi::FromInt(1))), &out); |
+ GotoIf(SmiEqual(num_results, SmiConstant(Smi::FromInt(1))), &out); |
// Store all remaining captures. |
- Node* const limit = a->IntPtrAdd( |
- a->IntPtrConstant(RegExpMatchInfo::kFirstCaptureIndex), num_indices); |
+ Node* const limit = IntPtrAdd( |
+ IntPtrConstant(RegExpMatchInfo::kFirstCaptureIndex), num_indices); |
- CVariable var_from_cursor(a, MachineType::PointerRepresentation()); |
- CVariable var_to_cursor(a, MachineType::PointerRepresentation()); |
+ Variable var_from_cursor(this, MachineType::PointerRepresentation()); |
+ Variable var_to_cursor(this, MachineType::PointerRepresentation()); |
- var_from_cursor.Bind( |
- a->IntPtrConstant(RegExpMatchInfo::kFirstCaptureIndex + 2)); |
- var_to_cursor.Bind(a->IntPtrConstant(1)); |
+ var_from_cursor.Bind(IntPtrConstant(RegExpMatchInfo::kFirstCaptureIndex + 2)); |
+ var_to_cursor.Bind(IntPtrConstant(1)); |
- CVariable* vars[] = {&var_from_cursor, &var_to_cursor}; |
- CLabel loop(a, 2, vars); |
+ Variable* vars[] = {&var_from_cursor, &var_to_cursor}; |
+ Label loop(this, 2, vars); |
- a->Goto(&loop); |
- a->Bind(&loop); |
+ Goto(&loop); |
+ Bind(&loop); |
{ |
Node* const from_cursor = var_from_cursor.value(); |
Node* const to_cursor = var_to_cursor.value(); |
- Node* const start = a->LoadFixedArrayElement(match_info, from_cursor); |
+ Node* const start = LoadFixedArrayElement(match_info, from_cursor); |
- CLabel next_iter(a); |
- a->GotoIf(a->SmiEqual(start, a->SmiConstant(Smi::FromInt(-1))), &next_iter); |
+ Label next_iter(this); |
+ GotoIf(SmiEqual(start, SmiConstant(Smi::FromInt(-1))), &next_iter); |
- Node* const from_cursor_plus1 = |
- a->IntPtrAdd(from_cursor, a->IntPtrConstant(1)); |
- Node* const end = a->LoadFixedArrayElement(match_info, from_cursor_plus1); |
+ Node* const from_cursor_plus1 = IntPtrAdd(from_cursor, IntPtrConstant(1)); |
+ Node* const end = LoadFixedArrayElement(match_info, from_cursor_plus1); |
- Node* const capture = a->SubString(context, string, start, end); |
- a->StoreFixedArrayElement(result_elements, to_cursor, capture); |
- a->Goto(&next_iter); |
+ Node* const capture = SubString(context, string, start, end); |
+ StoreFixedArrayElement(result_elements, to_cursor, capture); |
+ Goto(&next_iter); |
- a->Bind(&next_iter); |
- var_from_cursor.Bind(a->IntPtrAdd(from_cursor, a->IntPtrConstant(2))); |
- var_to_cursor.Bind(a->IntPtrAdd(to_cursor, a->IntPtrConstant(1))); |
- a->Branch(a->UintPtrLessThan(var_from_cursor.value(), limit), &loop, &out); |
+ Bind(&next_iter); |
+ var_from_cursor.Bind(IntPtrAdd(from_cursor, IntPtrConstant(2))); |
+ var_to_cursor.Bind(IntPtrAdd(to_cursor, IntPtrConstant(1))); |
+ Branch(UintPtrLessThan(var_from_cursor.value(), limit), &loop, &out); |
} |
- a->Bind(&out); |
+ Bind(&out); |
return result; |
} |
@@ -155,207 +211,202 @@ Node* ConstructNewResultFromMatchInfo(Isolate* isolate, CodeStubAssembler* a, |
// constructing the JSRegExpResult. Returns either null (if the RegExp did not |
// match) or a fixed array containing match indices as returned by |
// RegExpExecStub. |
-Node* RegExpPrototypeExecBodyWithoutResult( |
- CodeStubAssembler* a, Node* const context, Node* const regexp, |
- Node* const string, CLabel* if_didnotmatch, const bool is_fastpath) { |
- Isolate* const isolate = a->isolate(); |
+Node* RegExpBuiltinsAssembler::RegExpPrototypeExecBodyWithoutResult( |
+ Node* const context, Node* const regexp, Node* const string, |
+ Label* if_didnotmatch, const bool is_fastpath) { |
+ Isolate* const isolate = this->isolate(); |
- Node* const null = a->NullConstant(); |
- Node* const int_zero = a->IntPtrConstant(0); |
- Node* const smi_zero = a->SmiConstant(Smi::kZero); |
+ Node* const null = NullConstant(); |
+ Node* const int_zero = IntPtrConstant(0); |
+ Node* const smi_zero = SmiConstant(Smi::kZero); |
if (!is_fastpath) { |
- a->ThrowIfNotInstanceType(context, regexp, JS_REGEXP_TYPE, |
- "RegExp.prototype.exec"); |
+ ThrowIfNotInstanceType(context, regexp, JS_REGEXP_TYPE, |
+ "RegExp.prototype.exec"); |
} |
- CSA_ASSERT(a, a->IsStringInstanceType(a->LoadInstanceType(string))); |
- CSA_ASSERT(a, a->HasInstanceType(regexp, JS_REGEXP_TYPE)); |
+ CSA_ASSERT(this, IsStringInstanceType(LoadInstanceType(string))); |
+ CSA_ASSERT(this, HasInstanceType(regexp, JS_REGEXP_TYPE)); |
- CVariable var_result(a, MachineRepresentation::kTagged); |
- CLabel out(a); |
+ Variable var_result(this, MachineRepresentation::kTagged); |
+ Label out(this); |
- Node* const native_context = a->LoadNativeContext(context); |
- Node* const string_length = a->LoadStringLength(string); |
+ Node* const native_context = LoadNativeContext(context); |
+ Node* const string_length = LoadStringLength(string); |
// Check whether the regexp is global or sticky, which determines whether we |
// update last index later on. |
- Node* const flags = a->LoadObjectField(regexp, JSRegExp::kFlagsOffset); |
- Node* const is_global_or_sticky = |
- a->WordAnd(a->SmiUntag(flags), |
- a->IntPtrConstant(JSRegExp::kGlobal | JSRegExp::kSticky)); |
+ Node* const flags = LoadObjectField(regexp, JSRegExp::kFlagsOffset); |
+ Node* const is_global_or_sticky = WordAnd( |
+ SmiUntag(flags), IntPtrConstant(JSRegExp::kGlobal | JSRegExp::kSticky)); |
Node* const should_update_last_index = |
- a->WordNotEqual(is_global_or_sticky, int_zero); |
+ WordNotEqual(is_global_or_sticky, int_zero); |
// Grab and possibly update last index. |
- CLabel run_exec(a); |
- CVariable var_lastindex(a, MachineRepresentation::kTagged); |
+ Label run_exec(this); |
+ Variable var_lastindex(this, MachineRepresentation::kTagged); |
{ |
- CLabel if_doupdate(a), if_dontupdate(a); |
- a->Branch(should_update_last_index, &if_doupdate, &if_dontupdate); |
+ Label if_doupdate(this), if_dontupdate(this); |
+ Branch(should_update_last_index, &if_doupdate, &if_dontupdate); |
- a->Bind(&if_doupdate); |
+ Bind(&if_doupdate); |
{ |
Node* const regexp_lastindex = |
- LoadLastIndex(a, context, regexp, is_fastpath); |
+ LoadLastIndex(context, regexp, is_fastpath); |
var_lastindex.Bind(regexp_lastindex); |
// Omit ToLength if lastindex is a non-negative smi. |
{ |
- CLabel call_tolength(a, CLabel::kDeferred), next(a); |
- a->Branch(a->WordIsPositiveSmi(regexp_lastindex), &next, |
- &call_tolength); |
+ Label call_tolength(this, Label::kDeferred), next(this); |
+ Branch(WordIsPositiveSmi(regexp_lastindex), &next, &call_tolength); |
- a->Bind(&call_tolength); |
+ Bind(&call_tolength); |
{ |
Callable tolength_callable = CodeFactory::ToLength(isolate); |
var_lastindex.Bind( |
- a->CallStub(tolength_callable, context, regexp_lastindex)); |
- a->Goto(&next); |
+ CallStub(tolength_callable, context, regexp_lastindex)); |
+ Goto(&next); |
} |
- a->Bind(&next); |
+ Bind(&next); |
} |
Node* const lastindex = var_lastindex.value(); |
- CLabel if_isoob(a, CLabel::kDeferred); |
- a->GotoUnless(a->TaggedIsSmi(lastindex), &if_isoob); |
- a->GotoUnless(a->SmiLessThanOrEqual(lastindex, string_length), &if_isoob); |
- a->Goto(&run_exec); |
+ Label if_isoob(this, Label::kDeferred); |
+ GotoUnless(TaggedIsSmi(lastindex), &if_isoob); |
+ GotoUnless(SmiLessThanOrEqual(lastindex, string_length), &if_isoob); |
+ Goto(&run_exec); |
- a->Bind(&if_isoob); |
+ Bind(&if_isoob); |
{ |
- StoreLastIndex(a, context, regexp, smi_zero, is_fastpath); |
+ StoreLastIndex(context, regexp, smi_zero, is_fastpath); |
var_result.Bind(null); |
- a->Goto(if_didnotmatch); |
+ Goto(if_didnotmatch); |
} |
} |
- a->Bind(&if_dontupdate); |
+ Bind(&if_dontupdate); |
{ |
var_lastindex.Bind(smi_zero); |
- a->Goto(&run_exec); |
+ Goto(&run_exec); |
} |
} |
Node* match_indices; |
- CLabel successful_match(a); |
- a->Bind(&run_exec); |
+ Label successful_match(this); |
+ Bind(&run_exec); |
{ |
// Get last match info from the context. |
- Node* const last_match_info = a->LoadContextElement( |
+ Node* const last_match_info = LoadContextElement( |
native_context, Context::REGEXP_LAST_MATCH_INFO_INDEX); |
// Call the exec stub. |
Callable exec_callable = CodeFactory::RegExpExec(isolate); |
- match_indices = a->CallStub(exec_callable, context, regexp, string, |
- var_lastindex.value(), last_match_info); |
+ match_indices = CallStub(exec_callable, context, regexp, string, |
+ var_lastindex.value(), last_match_info); |
var_result.Bind(match_indices); |
// {match_indices} is either null or the RegExpMatchInfo array. |
// Return early if exec failed, possibly updating last index. |
- a->GotoUnless(a->WordEqual(match_indices, null), &successful_match); |
+ GotoUnless(WordEqual(match_indices, null), &successful_match); |
- a->GotoUnless(should_update_last_index, if_didnotmatch); |
+ GotoUnless(should_update_last_index, if_didnotmatch); |
- StoreLastIndex(a, context, regexp, smi_zero, is_fastpath); |
- a->Goto(if_didnotmatch); |
+ StoreLastIndex(context, regexp, smi_zero, is_fastpath); |
+ Goto(if_didnotmatch); |
} |
- a->Bind(&successful_match); |
+ Bind(&successful_match); |
{ |
- a->GotoUnless(should_update_last_index, &out); |
+ GotoUnless(should_update_last_index, &out); |
// Update the new last index from {match_indices}. |
- Node* const new_lastindex = a->LoadFixedArrayElement( |
+ Node* const new_lastindex = LoadFixedArrayElement( |
match_indices, RegExpMatchInfo::kFirstCaptureIndex + 1); |
- StoreLastIndex(a, context, regexp, new_lastindex, is_fastpath); |
- a->Goto(&out); |
+ StoreLastIndex(context, regexp, new_lastindex, is_fastpath); |
+ Goto(&out); |
} |
- a->Bind(&out); |
+ Bind(&out); |
return var_result.value(); |
} |
// ES#sec-regexp.prototype.exec |
// RegExp.prototype.exec ( string ) |
-Node* RegExpPrototypeExecBody(CodeStubAssembler* a, Node* const context, |
- Node* const regexp, Node* const string, |
- const bool is_fastpath) { |
- Isolate* const isolate = a->isolate(); |
- Node* const null = a->NullConstant(); |
+Node* RegExpBuiltinsAssembler::RegExpPrototypeExecBody(Node* const context, |
+ Node* const regexp, |
+ Node* const string, |
+ const bool is_fastpath) { |
+ Node* const null = NullConstant(); |
- CVariable var_result(a, MachineRepresentation::kTagged); |
+ Variable var_result(this, MachineRepresentation::kTagged); |
- CLabel if_didnotmatch(a), out(a); |
+ Label if_didnotmatch(this), out(this); |
Node* const indices_or_null = RegExpPrototypeExecBodyWithoutResult( |
- a, context, regexp, string, &if_didnotmatch, is_fastpath); |
+ context, regexp, string, &if_didnotmatch, is_fastpath); |
// Successful match. |
{ |
Node* const match_indices = indices_or_null; |
- Node* const result = ConstructNewResultFromMatchInfo(isolate, a, context, |
- match_indices, string); |
+ Node* const result = |
+ ConstructNewResultFromMatchInfo(context, match_indices, string); |
var_result.Bind(result); |
- a->Goto(&out); |
+ Goto(&out); |
} |
- a->Bind(&if_didnotmatch); |
+ Bind(&if_didnotmatch); |
{ |
var_result.Bind(null); |
- a->Goto(&out); |
+ Goto(&out); |
} |
- a->Bind(&out); |
+ Bind(&out); |
return var_result.value(); |
} |
-Node* ThrowIfNotJSReceiver(CodeStubAssembler* a, Isolate* isolate, |
- Node* context, Node* value, |
- MessageTemplate::Template msg_template, |
- char const* method_name) { |
- CLabel out(a), throw_exception(a, CLabel::kDeferred); |
- CVariable var_value_map(a, MachineRepresentation::kTagged); |
+Node* RegExpBuiltinsAssembler::ThrowIfNotJSReceiver( |
+ Node* context, Node* maybe_receiver, MessageTemplate::Template msg_template, |
+ char const* method_name) { |
+ Label out(this), throw_exception(this, Label::kDeferred); |
+ Variable var_value_map(this, MachineRepresentation::kTagged); |
- a->GotoIf(a->TaggedIsSmi(value), &throw_exception); |
+ GotoIf(TaggedIsSmi(maybe_receiver), &throw_exception); |
// Load the instance type of the {value}. |
- var_value_map.Bind(a->LoadMap(value)); |
- Node* const value_instance_type = |
- a->LoadMapInstanceType(var_value_map.value()); |
+ var_value_map.Bind(LoadMap(maybe_receiver)); |
+ Node* const value_instance_type = LoadMapInstanceType(var_value_map.value()); |
- a->Branch(a->IsJSReceiverInstanceType(value_instance_type), &out, |
- &throw_exception); |
+ Branch(IsJSReceiverInstanceType(value_instance_type), &out, &throw_exception); |
// The {value} is not a compatible receiver for this method. |
- a->Bind(&throw_exception); |
+ Bind(&throw_exception); |
{ |
- Node* const message_id = a->SmiConstant(Smi::FromInt(msg_template)); |
- Node* const method_name_str = a->HeapConstant( |
- isolate->factory()->NewStringFromAsciiChecked(method_name, TENURED)); |
+ Node* const message_id = SmiConstant(Smi::FromInt(msg_template)); |
+ Node* const method_name_str = HeapConstant( |
+ isolate()->factory()->NewStringFromAsciiChecked(method_name, TENURED)); |
- Callable callable = CodeFactory::ToString(isolate); |
- Node* const value_str = a->CallStub(callable, context, value); |
+ Callable callable = CodeFactory::ToString(isolate()); |
+ Node* const value_str = CallStub(callable, context, maybe_receiver); |
- a->CallRuntime(Runtime::kThrowTypeError, context, message_id, |
- method_name_str, value_str); |
- var_value_map.Bind(a->UndefinedConstant()); |
- a->Goto(&out); // Never reached. |
+ CallRuntime(Runtime::kThrowTypeError, context, message_id, method_name_str, |
+ value_str); |
+ var_value_map.Bind(UndefinedConstant()); |
+ Goto(&out); // Never reached. |
} |
- a->Bind(&out); |
+ Bind(&out); |
return var_value_map.value(); |
} |
-Node* IsInitialRegExpMap(CodeStubAssembler* a, Node* context, Node* map) { |
- Node* const native_context = a->LoadNativeContext(context); |
+Node* RegExpBuiltinsAssembler::IsInitialRegExpMap(Node* context, Node* map) { |
+ Node* const native_context = LoadNativeContext(context); |
Node* const regexp_fun = |
- a->LoadContextElement(native_context, Context::REGEXP_FUNCTION_INDEX); |
+ LoadContextElement(native_context, Context::REGEXP_FUNCTION_INDEX); |
Node* const initial_map = |
- a->LoadObjectField(regexp_fun, JSFunction::kPrototypeOrInitialMapOffset); |
- Node* const has_initialmap = a->WordEqual(map, initial_map); |
+ LoadObjectField(regexp_fun, JSFunction::kPrototypeOrInitialMapOffset); |
+ Node* const has_initialmap = WordEqual(map, initial_map); |
return has_initialmap; |
} |
@@ -364,41 +415,41 @@ Node* IsInitialRegExpMap(CodeStubAssembler* a, Node* context, Node* map) { |
// We use a fairly coarse granularity for this and simply check whether both |
// the regexp itself is unmodified (i.e. its map has not changed) and its |
// prototype is unmodified. |
-void BranchIfFastPath(CodeStubAssembler* a, Node* context, Node* map, |
- CLabel* if_isunmodified, CLabel* if_ismodified) { |
- Node* const native_context = a->LoadNativeContext(context); |
+void RegExpBuiltinsAssembler::BranchIfFastRegExp(Node* context, Node* map, |
+ Label* if_isunmodified, |
+ Label* if_ismodified) { |
+ Node* const native_context = LoadNativeContext(context); |
Node* const regexp_fun = |
- a->LoadContextElement(native_context, Context::REGEXP_FUNCTION_INDEX); |
+ LoadContextElement(native_context, Context::REGEXP_FUNCTION_INDEX); |
Node* const initial_map = |
- a->LoadObjectField(regexp_fun, JSFunction::kPrototypeOrInitialMapOffset); |
- Node* const has_initialmap = a->WordEqual(map, initial_map); |
+ LoadObjectField(regexp_fun, JSFunction::kPrototypeOrInitialMapOffset); |
+ Node* const has_initialmap = WordEqual(map, initial_map); |
- a->GotoUnless(has_initialmap, if_ismodified); |
+ GotoUnless(has_initialmap, if_ismodified); |
- Node* const initial_proto_initial_map = a->LoadContextElement( |
- native_context, Context::REGEXP_PROTOTYPE_MAP_INDEX); |
- Node* const proto_map = a->LoadMap(a->LoadMapPrototype(map)); |
+ Node* const initial_proto_initial_map = |
+ LoadContextElement(native_context, Context::REGEXP_PROTOTYPE_MAP_INDEX); |
+ Node* const proto_map = LoadMap(LoadMapPrototype(map)); |
Node* const proto_has_initialmap = |
- a->WordEqual(proto_map, initial_proto_initial_map); |
+ WordEqual(proto_map, initial_proto_initial_map); |
// TODO(ishell): Update this check once map changes for constant field |
// tracking are landing. |
- a->Branch(proto_has_initialmap, if_isunmodified, if_ismodified); |
+ Branch(proto_has_initialmap, if_isunmodified, if_ismodified); |
} |
-void BranchIfFastRegExpResult(CodeStubAssembler* a, Node* context, Node* map, |
- CLabel* if_isunmodified, CLabel* if_ismodified) { |
- Node* const native_context = a->LoadNativeContext(context); |
+void RegExpBuiltinsAssembler::BranchIfFastRegExpResult(Node* context, Node* map, |
+ Label* if_isunmodified, |
+ Label* if_ismodified) { |
+ Node* const native_context = LoadNativeContext(context); |
Node* const initial_regexp_result_map = |
- a->LoadContextElement(native_context, Context::REGEXP_RESULT_MAP_INDEX); |
+ LoadContextElement(native_context, Context::REGEXP_RESULT_MAP_INDEX); |
- a->Branch(a->WordEqual(map, initial_regexp_result_map), if_isunmodified, |
- if_ismodified); |
+ Branch(WordEqual(map, initial_regexp_result_map), if_isunmodified, |
+ if_ismodified); |
} |
-} // namespace |
- |
// ES#sec-regexp.prototype.exec |
// RegExp.prototype.exec ( string ) |
TF_BUILTIN(RegExpPrototypeExec, RegExpBuiltinsAssembler) { |
@@ -414,35 +465,34 @@ TF_BUILTIN(RegExpPrototypeExec, RegExpBuiltinsAssembler) { |
// Convert {maybe_string} to a String. |
Node* const string = ToString(context, maybe_string); |
- CLabel if_isfastpath(this), if_isslowpath(this); |
- Branch(IsInitialRegExpMap(this, context, regexp_map), &if_isfastpath, |
+ Label if_isfastpath(this), if_isslowpath(this); |
+ Branch(IsInitialRegExpMap(context, regexp_map), &if_isfastpath, |
&if_isslowpath); |
Bind(&if_isfastpath); |
{ |
Node* const result = |
- RegExpPrototypeExecBody(this, context, receiver, string, true); |
+ RegExpPrototypeExecBody(context, receiver, string, true); |
Return(result); |
} |
Bind(&if_isslowpath); |
{ |
Node* const result = |
- RegExpPrototypeExecBody(this, context, receiver, string, false); |
+ RegExpPrototypeExecBody(context, receiver, string, false); |
Return(result); |
} |
} |
-namespace { |
- |
-Node* FlagsGetter(CodeStubAssembler* a, Node* const receiver, |
- Node* const context, bool is_fastpath) { |
- Isolate* isolate = a->isolate(); |
+Node* RegExpBuiltinsAssembler::FlagsGetter(Node* const context, |
+ Node* const regexp, |
+ bool is_fastpath) { |
+ Isolate* isolate = this->isolate(); |
- Node* const int_zero = a->IntPtrConstant(0); |
- Node* const int_one = a->IntPtrConstant(1); |
- CVariable var_length(a, MachineType::PointerRepresentation()); |
- CVariable var_flags(a, MachineType::PointerRepresentation()); |
+ Node* const int_zero = IntPtrConstant(0); |
+ Node* const int_one = IntPtrConstant(1); |
+ Variable var_length(this, MachineType::PointerRepresentation()); |
+ Variable var_flags(this, MachineType::PointerRepresentation()); |
// First, count the number of characters we will need and check which flags |
// are set. |
@@ -451,18 +501,17 @@ Node* FlagsGetter(CodeStubAssembler* a, Node* const receiver, |
if (is_fastpath) { |
// Refer to JSRegExp's flag property on the fast-path. |
- Node* const flags_smi = |
- a->LoadObjectField(receiver, JSRegExp::kFlagsOffset); |
- Node* const flags_intptr = a->SmiUntag(flags_smi); |
+ Node* const flags_smi = LoadObjectField(regexp, JSRegExp::kFlagsOffset); |
+ Node* const flags_intptr = SmiUntag(flags_smi); |
var_flags.Bind(flags_intptr); |
-#define CASE_FOR_FLAG(FLAG) \ |
- do { \ |
- CLabel next(a); \ |
- a->GotoUnless(a->IsSetWord(flags_intptr, FLAG), &next); \ |
- var_length.Bind(a->IntPtrAdd(var_length.value(), int_one)); \ |
- a->Goto(&next); \ |
- a->Bind(&next); \ |
+#define CASE_FOR_FLAG(FLAG) \ |
+ do { \ |
+ Label next(this); \ |
+ GotoUnless(IsSetWord(flags_intptr, FLAG), &next); \ |
+ var_length.Bind(IntPtrAdd(var_length.value(), int_one)); \ |
+ Goto(&next); \ |
+ Bind(&next); \ |
} while (false) |
CASE_FOR_FLAG(JSRegExp::kGlobal); |
@@ -477,22 +526,21 @@ Node* FlagsGetter(CodeStubAssembler* a, Node* const receiver, |
// Fall back to GetProperty stub on the slow-path. |
var_flags.Bind(int_zero); |
- Callable getproperty_callable = CodeFactory::GetProperty(a->isolate()); |
- |
-#define CASE_FOR_FLAG(NAME, FLAG) \ |
- do { \ |
- CLabel next(a); \ |
- Node* const name = \ |
- a->HeapConstant(isolate->factory()->InternalizeUtf8String(NAME)); \ |
- Node* const flag = \ |
- a->CallStub(getproperty_callable, context, receiver, name); \ |
- CLabel if_isflagset(a); \ |
- a->BranchIfToBooleanIsTrue(flag, &if_isflagset, &next); \ |
- a->Bind(&if_isflagset); \ |
- var_length.Bind(a->IntPtrAdd(var_length.value(), int_one)); \ |
- var_flags.Bind(a->WordOr(var_flags.value(), a->IntPtrConstant(FLAG))); \ |
- a->Goto(&next); \ |
- a->Bind(&next); \ |
+ Callable getproperty_callable = CodeFactory::GetProperty(isolate); |
+ |
+#define CASE_FOR_FLAG(NAME, FLAG) \ |
+ do { \ |
+ Label next(this); \ |
+ Node* const name = \ |
+ HeapConstant(isolate->factory()->InternalizeUtf8String(NAME)); \ |
+ Node* const flag = CallStub(getproperty_callable, context, regexp, name); \ |
+ Label if_isflagset(this); \ |
+ BranchIfToBooleanIsTrue(flag, &if_isflagset, &next); \ |
+ Bind(&if_isflagset); \ |
+ var_length.Bind(IntPtrAdd(var_length.value(), int_one)); \ |
+ var_flags.Bind(WordOr(var_flags.value(), IntPtrConstant(FLAG))); \ |
+ Goto(&next); \ |
+ Bind(&next); \ |
} while (false) |
CASE_FOR_FLAG("global", JSRegExp::kGlobal); |
@@ -507,24 +555,23 @@ Node* FlagsGetter(CodeStubAssembler* a, Node* const receiver, |
// char for each set flag. |
{ |
- Node* const result = |
- a->AllocateSeqOneByteString(context, var_length.value()); |
+ Node* const result = AllocateSeqOneByteString(context, var_length.value()); |
Node* const flags_intptr = var_flags.value(); |
- CVariable var_offset(a, MachineType::PointerRepresentation()); |
+ Variable var_offset(this, MachineType::PointerRepresentation()); |
var_offset.Bind( |
- a->IntPtrConstant(SeqOneByteString::kHeaderSize - kHeapObjectTag)); |
- |
-#define CASE_FOR_FLAG(FLAG, CHAR) \ |
- do { \ |
- CLabel next(a); \ |
- a->GotoUnless(a->IsSetWord(flags_intptr, FLAG), &next); \ |
- Node* const value = a->IntPtrConstant(CHAR); \ |
- a->StoreNoWriteBarrier(MachineRepresentation::kWord8, result, \ |
- var_offset.value(), value); \ |
- var_offset.Bind(a->IntPtrAdd(var_offset.value(), int_one)); \ |
- a->Goto(&next); \ |
- a->Bind(&next); \ |
+ IntPtrConstant(SeqOneByteString::kHeaderSize - kHeapObjectTag)); |
+ |
+#define CASE_FOR_FLAG(FLAG, CHAR) \ |
+ do { \ |
+ Label next(this); \ |
+ GotoUnless(IsSetWord(flags_intptr, FLAG), &next); \ |
+ Node* const value = IntPtrConstant(CHAR); \ |
+ StoreNoWriteBarrier(MachineRepresentation::kWord8, result, \ |
+ var_offset.value(), value); \ |
+ var_offset.Bind(IntPtrAdd(var_offset.value(), int_one)); \ |
+ Goto(&next); \ |
+ Bind(&next); \ |
} while (false) |
CASE_FOR_FLAG(JSRegExp::kGlobal, 'g'); |
@@ -539,88 +586,83 @@ Node* FlagsGetter(CodeStubAssembler* a, Node* const receiver, |
} |
// ES#sec-isregexp IsRegExp ( argument ) |
-Node* IsRegExp(CodeStubAssembler* a, Node* const context, |
- Node* const maybe_receiver) { |
- CLabel out(a), if_isregexp(a); |
+Node* RegExpBuiltinsAssembler::IsRegExp(Node* const context, |
+ Node* const maybe_receiver) { |
+ Label out(this), if_isregexp(this); |
- CVariable var_result(a, MachineType::PointerRepresentation()); |
- var_result.Bind(a->IntPtrConstant(0)); |
+ Variable var_result(this, MachineType::PointerRepresentation()); |
+ var_result.Bind(IntPtrConstant(0)); |
- a->GotoIf(a->TaggedIsSmi(maybe_receiver), &out); |
- a->GotoUnless(a->IsJSReceiver(maybe_receiver), &out); |
+ GotoIf(TaggedIsSmi(maybe_receiver), &out); |
+ GotoUnless(IsJSReceiver(maybe_receiver), &out); |
Node* const receiver = maybe_receiver; |
// Check @@match. |
{ |
- Callable getproperty_callable = CodeFactory::GetProperty(a->isolate()); |
- Node* const name = a->HeapConstant(a->isolate()->factory()->match_symbol()); |
- Node* const value = |
- a->CallStub(getproperty_callable, context, receiver, name); |
+ Callable getproperty_callable = CodeFactory::GetProperty(isolate()); |
+ Node* const name = HeapConstant(isolate()->factory()->match_symbol()); |
+ Node* const value = CallStub(getproperty_callable, context, receiver, name); |
- CLabel match_isundefined(a), match_isnotundefined(a); |
- a->Branch(a->IsUndefined(value), &match_isundefined, &match_isnotundefined); |
+ Label match_isundefined(this), match_isnotundefined(this); |
+ Branch(IsUndefined(value), &match_isundefined, &match_isnotundefined); |
- a->Bind(&match_isundefined); |
- a->Branch(a->HasInstanceType(receiver, JS_REGEXP_TYPE), &if_isregexp, &out); |
+ Bind(&match_isundefined); |
+ Branch(HasInstanceType(receiver, JS_REGEXP_TYPE), &if_isregexp, &out); |
- a->Bind(&match_isnotundefined); |
- a->BranchIfToBooleanIsTrue(value, &if_isregexp, &out); |
+ Bind(&match_isnotundefined); |
+ BranchIfToBooleanIsTrue(value, &if_isregexp, &out); |
} |
- a->Bind(&if_isregexp); |
- var_result.Bind(a->IntPtrConstant(1)); |
- a->Goto(&out); |
+ Bind(&if_isregexp); |
+ var_result.Bind(IntPtrConstant(1)); |
+ Goto(&out); |
- a->Bind(&out); |
+ Bind(&out); |
return var_result.value(); |
} |
// ES#sec-regexpinitialize |
// Runtime Semantics: RegExpInitialize ( obj, pattern, flags ) |
-Node* RegExpInitialize(CodeStubAssembler* a, Node* const context, |
- Node* const regexp, Node* const maybe_pattern, |
- Node* const maybe_flags) { |
+Node* RegExpBuiltinsAssembler::RegExpInitialize(Node* const context, |
+ Node* const regexp, |
+ Node* const maybe_pattern, |
+ Node* const maybe_flags) { |
// Normalize pattern. |
- Node* const pattern = a->Select( |
- a->IsUndefined(maybe_pattern), [=] { return a->EmptyStringConstant(); }, |
- [=] { return a->ToString(context, maybe_pattern); }, |
- MachineRepresentation::kTagged); |
+ Node* const pattern = |
+ Select(IsUndefined(maybe_pattern), [=] { return EmptyStringConstant(); }, |
+ [=] { return ToString(context, maybe_pattern); }, |
+ MachineRepresentation::kTagged); |
// Normalize flags. |
- Node* const flags = a->Select( |
- a->IsUndefined(maybe_flags), [=] { return a->EmptyStringConstant(); }, |
- [=] { return a->ToString(context, maybe_flags); }, |
- MachineRepresentation::kTagged); |
+ Node* const flags = |
+ Select(IsUndefined(maybe_flags), [=] { return EmptyStringConstant(); }, |
+ [=] { return ToString(context, maybe_flags); }, |
+ MachineRepresentation::kTagged); |
// Initialize. |
- return a->CallRuntime(Runtime::kRegExpInitializeAndCompile, context, regexp, |
- pattern, flags); |
+ return CallRuntime(Runtime::kRegExpInitializeAndCompile, context, regexp, |
+ pattern, flags); |
} |
-} // namespace |
- |
TF_BUILTIN(RegExpPrototypeFlagsGetter, RegExpBuiltinsAssembler) { |
- Isolate* isolate = this->isolate(); |
- |
Node* const maybe_receiver = Parameter(0); |
Node* const context = Parameter(3); |
- Node* const map = ThrowIfNotJSReceiver(this, isolate, context, maybe_receiver, |
+ Node* const map = ThrowIfNotJSReceiver(context, maybe_receiver, |
MessageTemplate::kRegExpNonObject, |
"RegExp.prototype.flags"); |
Node* const receiver = maybe_receiver; |
- CLabel if_isfastpath(this), if_isslowpath(this, CLabel::kDeferred); |
- Branch(IsInitialRegExpMap(this, context, map), &if_isfastpath, |
- &if_isslowpath); |
+ Label if_isfastpath(this), if_isslowpath(this, Label::kDeferred); |
+ Branch(IsInitialRegExpMap(context, map), &if_isfastpath, &if_isslowpath); |
Bind(&if_isfastpath); |
- Return(FlagsGetter(this, receiver, context, true)); |
+ Return(FlagsGetter(context, receiver, true)); |
Bind(&if_isslowpath); |
- Return(FlagsGetter(this, receiver, context, false)); |
+ Return(FlagsGetter(context, receiver, false)); |
} |
// ES#sec-regexp-pattern-flags |
@@ -633,9 +675,9 @@ TF_BUILTIN(RegExpConstructor, RegExpBuiltinsAssembler) { |
Isolate* isolate = this->isolate(); |
- CVariable var_flags(this, MachineRepresentation::kTagged); |
- CVariable var_pattern(this, MachineRepresentation::kTagged); |
- CVariable var_new_target(this, MachineRepresentation::kTagged); |
+ Variable var_flags(this, MachineRepresentation::kTagged); |
+ Variable var_pattern(this, MachineRepresentation::kTagged); |
+ Variable var_new_target(this, MachineRepresentation::kTagged); |
var_flags.Bind(flags); |
var_pattern.Bind(pattern); |
@@ -645,10 +687,10 @@ TF_BUILTIN(RegExpConstructor, RegExpBuiltinsAssembler) { |
Node* const regexp_function = |
LoadContextElement(native_context, Context::REGEXP_FUNCTION_INDEX); |
- Node* const pattern_is_regexp = IsRegExp(this, context, pattern); |
+ Node* const pattern_is_regexp = IsRegExp(context, pattern); |
{ |
- CLabel next(this); |
+ Label next(this); |
GotoUnless(IsUndefined(new_target), &next); |
var_new_target.Bind(regexp_function); |
@@ -667,7 +709,7 @@ TF_BUILTIN(RegExpConstructor, RegExpBuiltinsAssembler) { |
} |
{ |
- CLabel next(this), if_patternisfastregexp(this), |
+ Label next(this), if_patternisfastregexp(this), |
if_patternisslowregexp(this); |
GotoIf(TaggedIsSmi(pattern), &next); |
@@ -681,10 +723,10 @@ TF_BUILTIN(RegExpConstructor, RegExpBuiltinsAssembler) { |
var_pattern.Bind(source); |
{ |
- CLabel inner_next(this); |
+ Label inner_next(this); |
GotoUnless(IsUndefined(flags), &inner_next); |
- Node* const value = FlagsGetter(this, pattern, context, true); |
+ Node* const value = FlagsGetter(context, pattern, true); |
var_flags.Bind(value); |
Goto(&inner_next); |
@@ -706,7 +748,7 @@ TF_BUILTIN(RegExpConstructor, RegExpBuiltinsAssembler) { |
} |
{ |
- CLabel inner_next(this); |
+ Label inner_next(this); |
GotoUnless(IsUndefined(flags), &inner_next); |
Node* const name = HeapConstant(isolate->factory()->flags_string()); |
@@ -726,9 +768,9 @@ TF_BUILTIN(RegExpConstructor, RegExpBuiltinsAssembler) { |
// Allocate. |
- CVariable var_regexp(this, MachineRepresentation::kTagged); |
+ Variable var_regexp(this, MachineRepresentation::kTagged); |
{ |
- CLabel allocate_jsregexp(this), allocate_generic(this, CLabel::kDeferred), |
+ Label allocate_jsregexp(this), allocate_generic(this, Label::kDeferred), |
next(this); |
Branch(WordEqual(var_new_target.value(), regexp_function), |
&allocate_jsregexp, &allocate_generic); |
@@ -754,7 +796,7 @@ TF_BUILTIN(RegExpConstructor, RegExpBuiltinsAssembler) { |
Bind(&next); |
} |
- Node* const result = RegExpInitialize(this, context, var_regexp.value(), |
+ Node* const result = RegExpInitialize(context, var_regexp.value(), |
var_pattern.value(), var_flags.value()); |
Return(result); |
} |
@@ -771,15 +813,15 @@ TF_BUILTIN(RegExpPrototypeCompile, RegExpBuiltinsAssembler) { |
"RegExp.prototype.compile"); |
Node* const receiver = maybe_receiver; |
- CVariable var_flags(this, MachineRepresentation::kTagged); |
- CVariable var_pattern(this, MachineRepresentation::kTagged); |
+ Variable var_flags(this, MachineRepresentation::kTagged); |
+ Variable var_pattern(this, MachineRepresentation::kTagged); |
var_flags.Bind(maybe_flags); |
var_pattern.Bind(maybe_pattern); |
// Handle a JSRegExp pattern. |
{ |
- CLabel next(this); |
+ Label next(this); |
GotoIf(TaggedIsSmi(maybe_pattern), &next); |
GotoUnless(HasInstanceType(maybe_pattern, JS_REGEXP_TYPE), &next); |
@@ -788,7 +830,7 @@ TF_BUILTIN(RegExpPrototypeCompile, RegExpBuiltinsAssembler) { |
// {maybe_flags} must be undefined in this case, otherwise throw. |
{ |
- CLabel next(this); |
+ Label next(this); |
GotoIf(IsUndefined(maybe_flags), &next); |
Node* const message_id = SmiConstant(MessageTemplate::kRegExpFlags); |
@@ -797,7 +839,7 @@ TF_BUILTIN(RegExpPrototypeCompile, RegExpBuiltinsAssembler) { |
Bind(&next); |
} |
- Node* const new_flags = FlagsGetter(this, pattern, context, true); |
+ Node* const new_flags = FlagsGetter(context, pattern, true); |
Node* const new_pattern = LoadObjectField(pattern, JSRegExp::kSourceOffset); |
var_flags.Bind(new_flags); |
@@ -807,8 +849,7 @@ TF_BUILTIN(RegExpPrototypeCompile, RegExpBuiltinsAssembler) { |
Bind(&next); |
} |
- RegExpInitialize(this, context, receiver, var_pattern.value(), |
- var_flags.value()); |
+ RegExpInitialize(context, receiver, var_pattern.value(), var_flags.value()); |
// Return undefined for compatibility with JSC. |
// See http://crbug.com/585775 for web compat details. |
@@ -822,7 +863,7 @@ TF_BUILTIN(RegExpPrototypeSourceGetter, RegExpBuiltinsAssembler) { |
Node* const context = Parameter(3); |
// Check whether we have an unmodified regexp instance. |
- CLabel if_isjsregexp(this), if_isnotjsregexp(this, CLabel::kDeferred); |
+ Label if_isjsregexp(this), if_isnotjsregexp(this, Label::kDeferred); |
GotoIf(TaggedIsSmi(receiver), &if_isnotjsregexp); |
Branch(HasInstanceType(receiver, JS_REGEXP_TYPE), &if_isjsregexp, |
@@ -844,7 +885,7 @@ TF_BUILTIN(RegExpPrototypeSourceGetter, RegExpBuiltinsAssembler) { |
LoadObjectField(regexp_fun, JSFunction::kPrototypeOrInitialMapOffset); |
Node* const initial_prototype = LoadMapPrototype(initial_map); |
- CLabel if_isprototype(this), if_isnotprototype(this); |
+ Label if_isprototype(this), if_isnotprototype(this); |
Branch(WordEqual(receiver, initial_prototype), &if_isprototype, |
&if_isnotprototype); |
@@ -915,175 +956,166 @@ TF_BUILTIN(RegExpPrototypeSpeciesGetter, RegExpBuiltinsAssembler) { |
Return(receiver); |
} |
-namespace { |
- |
// Fast-path implementation for flag checks on an unmodified JSRegExp instance. |
-Node* FastFlagGetter(CodeStubAssembler* a, Node* const regexp, |
- JSRegExp::Flag flag) { |
- Node* const smi_zero = a->SmiConstant(Smi::kZero); |
- Node* const flags = a->LoadObjectField(regexp, JSRegExp::kFlagsOffset); |
- Node* const mask = a->SmiConstant(Smi::FromInt(flag)); |
- Node* const is_flag_set = a->WordNotEqual(a->WordAnd(flags, mask), smi_zero); |
+Node* RegExpBuiltinsAssembler::FastFlagGetter(Node* const regexp, |
+ JSRegExp::Flag flag) { |
+ Node* const smi_zero = SmiConstant(Smi::kZero); |
+ Node* const flags = LoadObjectField(regexp, JSRegExp::kFlagsOffset); |
+ Node* const mask = SmiConstant(Smi::FromInt(flag)); |
+ Node* const is_flag_set = WordNotEqual(WordAnd(flags, mask), smi_zero); |
return is_flag_set; |
} |
// Load through the GetProperty stub. |
-compiler::Node* SlowFlagGetter(CodeStubAssembler* a, |
- compiler::Node* const context, |
- compiler::Node* const regexp, |
- JSRegExp::Flag flag) { |
- Factory* factory = a->isolate()->factory(); |
+Node* RegExpBuiltinsAssembler::SlowFlagGetter(Node* const context, |
+ Node* const regexp, |
+ JSRegExp::Flag flag) { |
+ Factory* factory = isolate()->factory(); |
- CLabel out(a); |
- CVariable var_result(a, MachineType::PointerRepresentation()); |
+ Label out(this); |
+ Variable var_result(this, MachineType::PointerRepresentation()); |
Node* name; |
switch (flag) { |
case JSRegExp::kGlobal: |
- name = a->HeapConstant(factory->global_string()); |
+ name = HeapConstant(factory->global_string()); |
break; |
case JSRegExp::kIgnoreCase: |
- name = a->HeapConstant(factory->ignoreCase_string()); |
+ name = HeapConstant(factory->ignoreCase_string()); |
break; |
case JSRegExp::kMultiline: |
- name = a->HeapConstant(factory->multiline_string()); |
+ name = HeapConstant(factory->multiline_string()); |
break; |
case JSRegExp::kSticky: |
- name = a->HeapConstant(factory->sticky_string()); |
+ name = HeapConstant(factory->sticky_string()); |
break; |
case JSRegExp::kUnicode: |
- name = a->HeapConstant(factory->unicode_string()); |
+ name = HeapConstant(factory->unicode_string()); |
break; |
default: |
UNREACHABLE(); |
} |
- Callable getproperty_callable = CodeFactory::GetProperty(a->isolate()); |
- Node* const value = a->CallStub(getproperty_callable, context, regexp, name); |
+ Callable getproperty_callable = CodeFactory::GetProperty(isolate()); |
+ Node* const value = CallStub(getproperty_callable, context, regexp, name); |
- CLabel if_true(a), if_false(a); |
- a->BranchIfToBooleanIsTrue(value, &if_true, &if_false); |
+ Label if_true(this), if_false(this); |
+ BranchIfToBooleanIsTrue(value, &if_true, &if_false); |
- a->Bind(&if_true); |
+ Bind(&if_true); |
{ |
- var_result.Bind(a->IntPtrConstant(1)); |
- a->Goto(&out); |
+ var_result.Bind(IntPtrConstant(1)); |
+ Goto(&out); |
} |
- a->Bind(&if_false); |
+ Bind(&if_false); |
{ |
- var_result.Bind(a->IntPtrConstant(0)); |
- a->Goto(&out); |
+ var_result.Bind(IntPtrConstant(0)); |
+ Goto(&out); |
} |
- a->Bind(&out); |
+ Bind(&out); |
return var_result.value(); |
} |
-compiler::Node* FlagGetter(CodeStubAssembler* a, compiler::Node* const context, |
- compiler::Node* const regexp, JSRegExp::Flag flag, |
- bool is_fastpath) { |
- return is_fastpath ? FastFlagGetter(a, regexp, flag) |
- : SlowFlagGetter(a, context, regexp, flag); |
+Node* RegExpBuiltinsAssembler::FlagGetter(Node* const context, |
+ Node* const regexp, |
+ JSRegExp::Flag flag, |
+ bool is_fastpath) { |
+ return is_fastpath ? FastFlagGetter(regexp, flag) |
+ : SlowFlagGetter(context, regexp, flag); |
} |
-void Generate_FlagGetter(CodeStubAssembler* a, JSRegExp::Flag flag, |
- v8::Isolate::UseCounterFeature counter, |
- const char* method_name) { |
- Node* const receiver = a->Parameter(0); |
- Node* const context = a->Parameter(3); |
+void RegExpBuiltinsAssembler::FlagGetter(JSRegExp::Flag flag, |
+ v8::Isolate::UseCounterFeature counter, |
+ const char* method_name) { |
+ Node* const receiver = Parameter(0); |
+ Node* const context = Parameter(3); |
- Isolate* isolate = a->isolate(); |
+ Isolate* isolate = this->isolate(); |
// Check whether we have an unmodified regexp instance. |
- CLabel if_isunmodifiedjsregexp(a), |
- if_isnotunmodifiedjsregexp(a, CLabel::kDeferred); |
+ Label if_isunmodifiedjsregexp(this), |
+ if_isnotunmodifiedjsregexp(this, Label::kDeferred); |
- a->GotoIf(a->TaggedIsSmi(receiver), &if_isnotunmodifiedjsregexp); |
+ GotoIf(TaggedIsSmi(receiver), &if_isnotunmodifiedjsregexp); |
- Node* const receiver_map = a->LoadMap(receiver); |
- Node* const instance_type = a->LoadMapInstanceType(receiver_map); |
+ Node* const receiver_map = LoadMap(receiver); |
+ Node* const instance_type = LoadMapInstanceType(receiver_map); |
- a->Branch(a->Word32Equal(instance_type, a->Int32Constant(JS_REGEXP_TYPE)), |
- &if_isunmodifiedjsregexp, &if_isnotunmodifiedjsregexp); |
+ Branch(Word32Equal(instance_type, Int32Constant(JS_REGEXP_TYPE)), |
+ &if_isunmodifiedjsregexp, &if_isnotunmodifiedjsregexp); |
- a->Bind(&if_isunmodifiedjsregexp); |
+ Bind(&if_isunmodifiedjsregexp); |
{ |
// Refer to JSRegExp's flag property on the fast-path. |
- Node* const is_flag_set = FastFlagGetter(a, receiver, flag); |
- a->Return(a->SelectBooleanConstant(is_flag_set)); |
+ Node* const is_flag_set = FastFlagGetter(receiver, flag); |
+ Return(SelectBooleanConstant(is_flag_set)); |
} |
- a->Bind(&if_isnotunmodifiedjsregexp); |
+ Bind(&if_isnotunmodifiedjsregexp); |
{ |
- Node* const native_context = a->LoadNativeContext(context); |
+ Node* const native_context = LoadNativeContext(context); |
Node* const regexp_fun = |
- a->LoadContextElement(native_context, Context::REGEXP_FUNCTION_INDEX); |
- Node* const initial_map = a->LoadObjectField( |
- regexp_fun, JSFunction::kPrototypeOrInitialMapOffset); |
- Node* const initial_prototype = a->LoadMapPrototype(initial_map); |
+ LoadContextElement(native_context, Context::REGEXP_FUNCTION_INDEX); |
+ Node* const initial_map = |
+ LoadObjectField(regexp_fun, JSFunction::kPrototypeOrInitialMapOffset); |
+ Node* const initial_prototype = LoadMapPrototype(initial_map); |
- CLabel if_isprototype(a), if_isnotprototype(a); |
- a->Branch(a->WordEqual(receiver, initial_prototype), &if_isprototype, |
- &if_isnotprototype); |
+ Label if_isprototype(this), if_isnotprototype(this); |
+ Branch(WordEqual(receiver, initial_prototype), &if_isprototype, |
+ &if_isnotprototype); |
- a->Bind(&if_isprototype); |
+ Bind(&if_isprototype); |
{ |
- Node* const counter_smi = a->SmiConstant(Smi::FromInt(counter)); |
- a->CallRuntime(Runtime::kIncrementUseCounter, context, counter_smi); |
- a->Return(a->UndefinedConstant()); |
+ Node* const counter_smi = SmiConstant(Smi::FromInt(counter)); |
+ CallRuntime(Runtime::kIncrementUseCounter, context, counter_smi); |
+ Return(UndefinedConstant()); |
} |
- a->Bind(&if_isnotprototype); |
+ Bind(&if_isnotprototype); |
{ |
Node* const message_id = |
- a->SmiConstant(Smi::FromInt(MessageTemplate::kRegExpNonRegExp)); |
- Node* const method_name_str = a->HeapConstant( |
+ SmiConstant(Smi::FromInt(MessageTemplate::kRegExpNonRegExp)); |
+ Node* const method_name_str = HeapConstant( |
isolate->factory()->NewStringFromAsciiChecked(method_name)); |
- a->CallRuntime(Runtime::kThrowTypeError, context, message_id, |
- method_name_str); |
- a->Return(a->UndefinedConstant()); // Never reached. |
+ CallRuntime(Runtime::kThrowTypeError, context, message_id, |
+ method_name_str); |
+ Return(UndefinedConstant()); // Never reached. |
} |
} |
} |
-} // namespace |
- |
// ES6 21.2.5.4. |
TF_BUILTIN(RegExpPrototypeGlobalGetter, RegExpBuiltinsAssembler) { |
- Generate_FlagGetter(this, JSRegExp::kGlobal, |
- v8::Isolate::kRegExpPrototypeOldFlagGetter, |
- "RegExp.prototype.global"); |
+ FlagGetter(JSRegExp::kGlobal, v8::Isolate::kRegExpPrototypeOldFlagGetter, |
+ "RegExp.prototype.global"); |
} |
// ES6 21.2.5.5. |
TF_BUILTIN(RegExpPrototypeIgnoreCaseGetter, RegExpBuiltinsAssembler) { |
- Generate_FlagGetter(this, JSRegExp::kIgnoreCase, |
- v8::Isolate::kRegExpPrototypeOldFlagGetter, |
- "RegExp.prototype.ignoreCase"); |
+ FlagGetter(JSRegExp::kIgnoreCase, v8::Isolate::kRegExpPrototypeOldFlagGetter, |
+ "RegExp.prototype.ignoreCase"); |
} |
// ES6 21.2.5.7. |
TF_BUILTIN(RegExpPrototypeMultilineGetter, RegExpBuiltinsAssembler) { |
- Generate_FlagGetter(this, JSRegExp::kMultiline, |
- v8::Isolate::kRegExpPrototypeOldFlagGetter, |
- "RegExp.prototype.multiline"); |
+ FlagGetter(JSRegExp::kMultiline, v8::Isolate::kRegExpPrototypeOldFlagGetter, |
+ "RegExp.prototype.multiline"); |
} |
// ES6 21.2.5.12. |
TF_BUILTIN(RegExpPrototypeStickyGetter, RegExpBuiltinsAssembler) { |
- Generate_FlagGetter(this, JSRegExp::kSticky, |
- v8::Isolate::kRegExpPrototypeStickyGetter, |
- "RegExp.prototype.sticky"); |
+ FlagGetter(JSRegExp::kSticky, v8::Isolate::kRegExpPrototypeStickyGetter, |
+ "RegExp.prototype.sticky"); |
} |
// ES6 21.2.5.15. |
TF_BUILTIN(RegExpPrototypeUnicodeGetter, RegExpBuiltinsAssembler) { |
- Generate_FlagGetter(this, JSRegExp::kUnicode, |
- v8::Isolate::kRegExpPrototypeUnicodeGetter, |
- "RegExp.prototype.unicode"); |
+ FlagGetter(JSRegExp::kUnicode, v8::Isolate::kRegExpPrototypeUnicodeGetter, |
+ "RegExp.prototype.unicode"); |
} |
// The properties $1..$9 are the first nine capturing substrings of the last |
@@ -1169,105 +1201,97 @@ BUILTIN(RegExpRightContextGetter) { |
return *isolate->factory()->NewSubString(last_subject, start_index, len); |
} |
-namespace { |
- |
// ES#sec-regexpexec Runtime Semantics: RegExpExec ( R, S ) |
-Node* RegExpExec(CodeStubAssembler* a, Node* context, Node* recv, |
- Node* string) { |
- Isolate* isolate = a->isolate(); |
+Node* RegExpBuiltinsAssembler::RegExpExec(Node* context, Node* regexp, |
+ Node* string) { |
+ Isolate* isolate = this->isolate(); |
- Node* const null = a->NullConstant(); |
+ Node* const null = NullConstant(); |
- CVariable var_result(a, MachineRepresentation::kTagged); |
- CLabel out(a), if_isfastpath(a), if_isslowpath(a); |
+ Variable var_result(this, MachineRepresentation::kTagged); |
+ Label out(this), if_isfastpath(this), if_isslowpath(this); |
- Node* const map = a->LoadMap(recv); |
- BranchIfFastPath(a, context, map, &if_isfastpath, &if_isslowpath); |
+ Node* const map = LoadMap(regexp); |
+ BranchIfFastRegExp(context, map, &if_isfastpath, &if_isslowpath); |
- a->Bind(&if_isfastpath); |
+ Bind(&if_isfastpath); |
{ |
- Node* const result = |
- RegExpPrototypeExecBody(a, context, recv, string, true); |
+ Node* const result = RegExpPrototypeExecBody(context, regexp, string, true); |
var_result.Bind(result); |
- a->Goto(&out); |
+ Goto(&out); |
} |
- a->Bind(&if_isslowpath); |
+ Bind(&if_isslowpath); |
{ |
// Take the slow path of fetching the exec property, calling it, and |
// verifying its return value. |
// Get the exec property. |
- Node* const name = a->HeapConstant(isolate->factory()->exec_string()); |
- Callable getproperty_callable = CodeFactory::GetProperty(a->isolate()); |
- Node* const exec = a->CallStub(getproperty_callable, context, recv, name); |
+ Node* const name = HeapConstant(isolate->factory()->exec_string()); |
+ Callable getproperty_callable = CodeFactory::GetProperty(isolate); |
+ Node* const exec = CallStub(getproperty_callable, context, regexp, name); |
// Is {exec} callable? |
- CLabel if_iscallable(a), if_isnotcallable(a); |
+ Label if_iscallable(this), if_isnotcallable(this); |
- a->GotoIf(a->TaggedIsSmi(exec), &if_isnotcallable); |
+ GotoIf(TaggedIsSmi(exec), &if_isnotcallable); |
- Node* const exec_map = a->LoadMap(exec); |
- a->Branch(a->IsCallableMap(exec_map), &if_iscallable, &if_isnotcallable); |
+ Node* const exec_map = LoadMap(exec); |
+ Branch(IsCallableMap(exec_map), &if_iscallable, &if_isnotcallable); |
- a->Bind(&if_iscallable); |
+ Bind(&if_iscallable); |
{ |
Callable call_callable = CodeFactory::Call(isolate); |
- Node* const result = |
- a->CallJS(call_callable, context, exec, recv, string); |
+ Node* const result = CallJS(call_callable, context, exec, regexp, string); |
var_result.Bind(result); |
- a->GotoIf(a->WordEqual(result, null), &out); |
+ GotoIf(WordEqual(result, null), &out); |
- ThrowIfNotJSReceiver(a, isolate, context, result, |
+ ThrowIfNotJSReceiver(context, result, |
MessageTemplate::kInvalidRegExpExecResult, "unused"); |
- a->Goto(&out); |
+ Goto(&out); |
} |
- a->Bind(&if_isnotcallable); |
+ Bind(&if_isnotcallable); |
{ |
- a->ThrowIfNotInstanceType(context, recv, JS_REGEXP_TYPE, |
- "RegExp.prototype.exec"); |
+ ThrowIfNotInstanceType(context, regexp, JS_REGEXP_TYPE, |
+ "RegExp.prototype.exec"); |
Node* const result = |
- RegExpPrototypeExecBody(a, context, recv, string, false); |
+ RegExpPrototypeExecBody(context, regexp, string, false); |
var_result.Bind(result); |
- a->Goto(&out); |
+ Goto(&out); |
} |
} |
- a->Bind(&out); |
+ Bind(&out); |
return var_result.value(); |
} |
-} // namespace |
- |
// ES#sec-regexp.prototype.test |
// RegExp.prototype.test ( S ) |
TF_BUILTIN(RegExpPrototypeTest, RegExpBuiltinsAssembler) { |
- Isolate* const isolate = this->isolate(); |
- |
Node* const maybe_receiver = Parameter(0); |
Node* const maybe_string = Parameter(1); |
Node* const context = Parameter(4); |
// Ensure {maybe_receiver} is a JSReceiver. |
Node* const map = ThrowIfNotJSReceiver( |
- this, isolate, context, maybe_receiver, |
- MessageTemplate::kIncompatibleMethodReceiver, "RegExp.prototype.test"); |
+ context, maybe_receiver, MessageTemplate::kIncompatibleMethodReceiver, |
+ "RegExp.prototype.test"); |
Node* const receiver = maybe_receiver; |
// Convert {maybe_string} to a String. |
Node* const string = ToString(context, maybe_string); |
- CLabel fast_path(this), slow_path(this); |
- BranchIfFastPath(this, context, map, &fast_path, &slow_path); |
+ Label fast_path(this), slow_path(this); |
+ BranchIfFastRegExp(context, map, &fast_path, &slow_path); |
Bind(&fast_path); |
{ |
- CLabel if_didnotmatch(this); |
- RegExpPrototypeExecBodyWithoutResult(this, context, receiver, string, |
+ Label if_didnotmatch(this); |
+ RegExpPrototypeExecBodyWithoutResult(context, receiver, string, |
&if_didnotmatch, true); |
Return(TrueConstant()); |
@@ -1278,7 +1302,7 @@ TF_BUILTIN(RegExpPrototypeTest, RegExpBuiltinsAssembler) { |
Bind(&slow_path); |
{ |
// Call exec. |
- Node* const match_indices = RegExpExec(this, context, receiver, string); |
+ Node* const match_indices = RegExpExec(context, receiver, string); |
// Return true iff exec matched successfully. |
Node* const result = |
@@ -1287,47 +1311,51 @@ TF_BUILTIN(RegExpPrototypeTest, RegExpBuiltinsAssembler) { |
} |
} |
-namespace { |
- |
-Node* AdvanceStringIndex(CodeStubAssembler* a, Node* const string, |
- Node* const index, Node* const is_unicode) { |
- CVariable var_result(a, MachineRepresentation::kTagged); |
+Node* RegExpBuiltinsAssembler::AdvanceStringIndex(Node* const string, |
+ Node* const index, |
+ Node* const is_unicode) { |
+ Variable var_result(this, MachineRepresentation::kTagged); |
// Default to last_index + 1. |
- Node* const index_plus_one = a->SmiAdd(index, a->SmiConstant(1)); |
+ Node* const index_plus_one = SmiAdd(index, SmiConstant(1)); |
var_result.Bind(index_plus_one); |
- CLabel if_isunicode(a), out(a); |
- a->Branch(is_unicode, &if_isunicode, &out); |
+ Label if_isunicode(this), out(this); |
+ Branch(is_unicode, &if_isunicode, &out); |
- a->Bind(&if_isunicode); |
+ Bind(&if_isunicode); |
{ |
- Node* const string_length = a->LoadStringLength(string); |
- a->GotoUnless(a->SmiLessThan(index_plus_one, string_length), &out); |
+ Node* const string_length = LoadStringLength(string); |
+ GotoUnless(SmiLessThan(index_plus_one, string_length), &out); |
- Node* const lead = a->StringCharCodeAt(string, index); |
- a->GotoUnless(a->Word32Equal(a->Word32And(lead, a->Int32Constant(0xFC00)), |
- a->Int32Constant(0xD800)), |
- &out); |
+ Node* const lead = StringCharCodeAt(string, index); |
+ GotoUnless(Word32Equal(Word32And(lead, Int32Constant(0xFC00)), |
+ Int32Constant(0xD800)), |
+ &out); |
- Node* const trail = a->StringCharCodeAt(string, index_plus_one); |
- a->GotoUnless(a->Word32Equal(a->Word32And(trail, a->Int32Constant(0xFC00)), |
- a->Int32Constant(0xDC00)), |
- &out); |
+ Node* const trail = StringCharCodeAt(string, index_plus_one); |
+ GotoUnless(Word32Equal(Word32And(trail, Int32Constant(0xFC00)), |
+ Int32Constant(0xDC00)), |
+ &out); |
// At a surrogate pair, return index + 2. |
- Node* const index_plus_two = a->SmiAdd(index, a->SmiConstant(2)); |
+ Node* const index_plus_two = SmiAdd(index, SmiConstant(2)); |
var_result.Bind(index_plus_two); |
- a->Goto(&out); |
+ Goto(&out); |
} |
- a->Bind(&out); |
+ Bind(&out); |
return var_result.value(); |
} |
+namespace { |
+ |
// Utility class implementing a growable fixed array through CSA. |
class GrowableFixedArray { |
+ typedef CodeStubAssembler::Label Label; |
+ typedef CodeStubAssembler::Variable Variable; |
+ |
public: |
explicit GrowableFixedArray(CodeStubAssembler* a) |
: assembler_(a), |
@@ -1339,9 +1367,9 @@ class GrowableFixedArray { |
Node* length() const { return var_length_.value(); } |
- CVariable* var_array() { return &var_array_; } |
- CVariable* var_length() { return &var_length_; } |
- CVariable* var_capacity() { return &var_capacity_; } |
+ Variable* var_array() { return &var_array_; } |
+ Variable* var_length() { return &var_length_; } |
+ Variable* var_capacity() { return &var_capacity_; } |
void Push(Node* const value) { |
CodeStubAssembler* a = assembler_; |
@@ -1352,7 +1380,7 @@ class GrowableFixedArray { |
Node* const length = var_length_.value(); |
Node* const capacity = var_capacity_.value(); |
- CLabel grow(a), store(a); |
+ Label grow(a), store(a); |
a->Branch(a->IntPtrEqual(capacity, length), &grow, &store); |
a->Bind(&grow); |
@@ -1449,121 +1477,123 @@ class GrowableFixedArray { |
private: |
CodeStubAssembler* const assembler_; |
- CVariable var_array_; |
- CVariable var_length_; |
- CVariable var_capacity_; |
+ Variable var_array_; |
+ Variable var_length_; |
+ Variable var_capacity_; |
}; |
-void RegExpPrototypeMatchBody(CodeStubAssembler* a, Node* const receiver, |
- Node* const string, Node* const context, |
- const bool is_fastpath) { |
- Isolate* const isolate = a->isolate(); |
+} // namespace |
- Node* const null = a->NullConstant(); |
- Node* const int_zero = a->IntPtrConstant(0); |
- Node* const smi_zero = a->SmiConstant(Smi::kZero); |
+void RegExpBuiltinsAssembler::RegExpPrototypeMatchBody(Node* const context, |
+ Node* const regexp, |
+ Node* const string, |
+ const bool is_fastpath) { |
+ Isolate* const isolate = this->isolate(); |
+ |
+ Node* const null = NullConstant(); |
+ Node* const int_zero = IntPtrConstant(0); |
+ Node* const smi_zero = SmiConstant(Smi::kZero); |
- Node* const regexp = receiver; |
Node* const is_global = |
- FlagGetter(a, context, regexp, JSRegExp::kGlobal, is_fastpath); |
+ FlagGetter(context, regexp, JSRegExp::kGlobal, is_fastpath); |
- CLabel if_isglobal(a), if_isnotglobal(a); |
- a->Branch(is_global, &if_isglobal, &if_isnotglobal); |
+ Label if_isglobal(this), if_isnotglobal(this); |
+ Branch(is_global, &if_isglobal, &if_isnotglobal); |
- a->Bind(&if_isnotglobal); |
+ Bind(&if_isnotglobal); |
{ |
Node* const result = |
- is_fastpath ? RegExpPrototypeExecBody(a, context, regexp, string, true) |
- : RegExpExec(a, context, regexp, string); |
- a->Return(result); |
+ is_fastpath ? RegExpPrototypeExecBody(context, regexp, string, true) |
+ : RegExpExec(context, regexp, string); |
+ Return(result); |
} |
- a->Bind(&if_isglobal); |
+ Bind(&if_isglobal); |
{ |
Node* const is_unicode = |
- FlagGetter(a, context, regexp, JSRegExp::kUnicode, is_fastpath); |
+ FlagGetter(context, regexp, JSRegExp::kUnicode, is_fastpath); |
- StoreLastIndex(a, context, regexp, smi_zero, is_fastpath); |
+ StoreLastIndex(context, regexp, smi_zero, is_fastpath); |
// Allocate an array to store the resulting match strings. |
- GrowableFixedArray array(a); |
+ GrowableFixedArray array(this); |
// Loop preparations. Within the loop, collect results from RegExpExec |
// and store match strings in the array. |
- CVariable* vars[] = {array.var_array(), array.var_length(), |
- array.var_capacity()}; |
- CLabel loop(a, 3, vars), out(a); |
- a->Goto(&loop); |
+ Variable* vars[] = {array.var_array(), array.var_length(), |
+ array.var_capacity()}; |
+ Label loop(this, 3, vars), out(this); |
+ Goto(&loop); |
- a->Bind(&loop); |
+ Bind(&loop); |
{ |
- CVariable var_match(a, MachineRepresentation::kTagged); |
+ Variable var_match(this, MachineRepresentation::kTagged); |
- CLabel if_didmatch(a), if_didnotmatch(a); |
+ Label if_didmatch(this), if_didnotmatch(this); |
if (is_fastpath) { |
// On the fast path, grab the matching string from the raw match index |
// array. |
Node* const match_indices = RegExpPrototypeExecBodyWithoutResult( |
- a, context, regexp, string, &if_didnotmatch, true); |
+ context, regexp, string, &if_didnotmatch, true); |
- Node* const match_from = a->LoadFixedArrayElement( |
+ Node* const match_from = LoadFixedArrayElement( |
match_indices, RegExpMatchInfo::kFirstCaptureIndex); |
- Node* const match_to = a->LoadFixedArrayElement( |
+ Node* const match_to = LoadFixedArrayElement( |
match_indices, RegExpMatchInfo::kFirstCaptureIndex + 1); |
- Node* match = a->SubString(context, string, match_from, match_to); |
+ Node* match = SubString(context, string, match_from, match_to); |
var_match.Bind(match); |
- a->Goto(&if_didmatch); |
+ Goto(&if_didmatch); |
} else { |
DCHECK(!is_fastpath); |
- Node* const result = RegExpExec(a, context, regexp, string); |
+ Node* const result = RegExpExec(context, regexp, string); |
- CLabel load_match(a); |
- a->Branch(a->WordEqual(result, null), &if_didnotmatch, &load_match); |
+ Label load_match(this); |
+ Branch(WordEqual(result, null), &if_didnotmatch, &load_match); |
- a->Bind(&load_match); |
+ Bind(&load_match); |
{ |
- CLabel fast_result(a), slow_result(a); |
- BranchIfFastRegExpResult(a, context, a->LoadMap(result), &fast_result, |
+ Label fast_result(this), slow_result(this); |
+ BranchIfFastRegExpResult(context, LoadMap(result), &fast_result, |
&slow_result); |
- a->Bind(&fast_result); |
+ Bind(&fast_result); |
{ |
- Node* const result_fixed_array = a->LoadElements(result); |
- Node* const match = a->LoadFixedArrayElement(result_fixed_array, 0); |
+ Node* const result_fixed_array = LoadElements(result); |
+ Node* const match = LoadFixedArrayElement(result_fixed_array, 0); |
// The match is guaranteed to be a string on the fast path. |
- CSA_ASSERT(a, a->IsStringInstanceType(a->LoadInstanceType(match))); |
+ CSA_ASSERT(this, IsStringInstanceType(LoadInstanceType(match))); |
var_match.Bind(match); |
- a->Goto(&if_didmatch); |
+ Goto(&if_didmatch); |
} |
- a->Bind(&slow_result); |
+ Bind(&slow_result); |
{ |
// TODO(ishell): Use GetElement stub once it's available. |
Node* const name = smi_zero; |
Callable getproperty_callable = CodeFactory::GetProperty(isolate); |
Node* const match = |
- a->CallStub(getproperty_callable, context, result, name); |
+ CallStub(getproperty_callable, context, result, name); |
- var_match.Bind(a->ToString(context, match)); |
- a->Goto(&if_didmatch); |
+ var_match.Bind(ToString(context, match)); |
+ Goto(&if_didmatch); |
} |
} |
} |
- a->Bind(&if_didnotmatch); |
+ Bind(&if_didnotmatch); |
{ |
// Return null if there were no matches, otherwise just exit the loop. |
- a->GotoUnless(a->IntPtrEqual(array.length(), int_zero), &out); |
- a->Return(null); |
+ GotoUnless(IntPtrEqual(array.length(), int_zero), &out); |
+ Return(null); |
} |
- a->Bind(&if_didmatch); |
+ Bind(&if_didmatch); |
{ |
Node* match = var_match.value(); |
@@ -1573,35 +1603,33 @@ void RegExpPrototypeMatchBody(CodeStubAssembler* a, Node* const receiver, |
// Advance last index if the match is the empty string. |
- Node* const match_length = a->LoadStringLength(match); |
- a->GotoUnless(a->SmiEqual(match_length, smi_zero), &loop); |
+ Node* const match_length = LoadStringLength(match); |
+ GotoUnless(SmiEqual(match_length, smi_zero), &loop); |
- Node* last_index = LoadLastIndex(a, context, regexp, is_fastpath); |
+ Node* last_index = LoadLastIndex(context, regexp, is_fastpath); |
Callable tolength_callable = CodeFactory::ToLength(isolate); |
- last_index = a->CallStub(tolength_callable, context, last_index); |
+ last_index = CallStub(tolength_callable, context, last_index); |
Node* const new_last_index = |
- AdvanceStringIndex(a, string, last_index, is_unicode); |
+ AdvanceStringIndex(string, last_index, is_unicode); |
- StoreLastIndex(a, context, regexp, new_last_index, is_fastpath); |
+ StoreLastIndex(context, regexp, new_last_index, is_fastpath); |
- a->Goto(&loop); |
+ Goto(&loop); |
} |
} |
- a->Bind(&out); |
+ Bind(&out); |
{ |
// Wrap the match in a JSArray. |
Node* const result = array.ToJSArray(context); |
- a->Return(result); |
+ Return(result); |
} |
} |
} |
-} // namespace |
- |
// ES#sec-regexp.prototype-@@match |
// RegExp.prototype [ @@match ] ( string ) |
TF_BUILTIN(RegExpPrototypeMatch, RegExpBuiltinsAssembler) { |
@@ -1611,299 +1639,288 @@ TF_BUILTIN(RegExpPrototypeMatch, RegExpBuiltinsAssembler) { |
// Ensure {maybe_receiver} is a JSReceiver. |
Node* const map = ThrowIfNotJSReceiver( |
- this, isolate(), context, maybe_receiver, |
- MessageTemplate::kIncompatibleMethodReceiver, "RegExp.prototype.@@match"); |
+ context, maybe_receiver, MessageTemplate::kIncompatibleMethodReceiver, |
+ "RegExp.prototype.@@match"); |
Node* const receiver = maybe_receiver; |
// Convert {maybe_string} to a String. |
Node* const string = ToString(context, maybe_string); |
- CLabel fast_path(this), slow_path(this); |
- BranchIfFastPath(this, context, map, &fast_path, &slow_path); |
+ Label fast_path(this), slow_path(this); |
+ BranchIfFastRegExp(context, map, &fast_path, &slow_path); |
Bind(&fast_path); |
- RegExpPrototypeMatchBody(this, receiver, string, context, true); |
+ RegExpPrototypeMatchBody(context, receiver, string, true); |
Bind(&slow_path); |
- RegExpPrototypeMatchBody(this, receiver, string, context, false); |
+ RegExpPrototypeMatchBody(context, receiver, string, false); |
} |
-namespace { |
- |
-void RegExpPrototypeSearchBodyFast(CodeStubAssembler* a, Node* const receiver, |
- Node* const string, Node* const context) { |
+void RegExpBuiltinsAssembler::RegExpPrototypeSearchBodyFast( |
+ Node* const context, Node* const regexp, Node* const string) { |
// Grab the initial value of last index. |
- Node* const previous_last_index = FastLoadLastIndex(a, receiver); |
+ Node* const previous_last_index = FastLoadLastIndex(regexp); |
// Ensure last index is 0. |
- FastStoreLastIndex(a, receiver, a->SmiConstant(Smi::kZero)); |
+ FastStoreLastIndex(regexp, SmiConstant(Smi::kZero)); |
// Call exec. |
- CLabel if_didnotmatch(a); |
+ Label if_didnotmatch(this); |
Node* const match_indices = RegExpPrototypeExecBodyWithoutResult( |
- a, context, receiver, string, &if_didnotmatch, true); |
+ context, regexp, string, &if_didnotmatch, true); |
// Successful match. |
{ |
// Reset last index. |
- FastStoreLastIndex(a, receiver, previous_last_index); |
+ FastStoreLastIndex(regexp, previous_last_index); |
// Return the index of the match. |
- Node* const index = a->LoadFixedArrayElement( |
+ Node* const index = LoadFixedArrayElement( |
match_indices, RegExpMatchInfo::kFirstCaptureIndex); |
- a->Return(index); |
+ Return(index); |
} |
- a->Bind(&if_didnotmatch); |
+ Bind(&if_didnotmatch); |
{ |
// Reset last index and return -1. |
- FastStoreLastIndex(a, receiver, previous_last_index); |
- a->Return(a->SmiConstant(-1)); |
+ FastStoreLastIndex(regexp, previous_last_index); |
+ Return(SmiConstant(-1)); |
} |
} |
-void RegExpPrototypeSearchBodySlow(CodeStubAssembler* a, Node* const receiver, |
- Node* const string, Node* const context) { |
- Isolate* const isolate = a->isolate(); |
+void RegExpBuiltinsAssembler::RegExpPrototypeSearchBodySlow( |
+ Node* const context, Node* const regexp, Node* const string) { |
+ Isolate* const isolate = this->isolate(); |
- Node* const smi_zero = a->SmiConstant(Smi::kZero); |
+ Node* const smi_zero = SmiConstant(Smi::kZero); |
// Grab the initial value of last index. |
- Node* const previous_last_index = SlowLoadLastIndex(a, context, receiver); |
+ Node* const previous_last_index = SlowLoadLastIndex(context, regexp); |
// Ensure last index is 0. |
{ |
- CLabel next(a); |
- a->GotoIf(a->SameValue(previous_last_index, smi_zero, context), &next); |
+ Label next(this); |
+ GotoIf(SameValue(previous_last_index, smi_zero, context), &next); |
- SlowStoreLastIndex(a, context, receiver, smi_zero); |
- a->Goto(&next); |
- a->Bind(&next); |
+ SlowStoreLastIndex(context, regexp, smi_zero); |
+ Goto(&next); |
+ Bind(&next); |
} |
// Call exec. |
- Node* const exec_result = RegExpExec(a, context, receiver, string); |
+ Node* const exec_result = RegExpExec(context, regexp, string); |
// Reset last index if necessary. |
{ |
- CLabel next(a); |
- Node* const current_last_index = SlowLoadLastIndex(a, context, receiver); |
+ Label next(this); |
+ Node* const current_last_index = SlowLoadLastIndex(context, regexp); |
- a->GotoIf(a->SameValue(current_last_index, previous_last_index, context), |
- &next); |
+ GotoIf(SameValue(current_last_index, previous_last_index, context), &next); |
- SlowStoreLastIndex(a, context, receiver, previous_last_index); |
- a->Goto(&next); |
+ SlowStoreLastIndex(context, regexp, previous_last_index); |
+ Goto(&next); |
- a->Bind(&next); |
+ Bind(&next); |
} |
// Return -1 if no match was found. |
{ |
- CLabel next(a); |
- a->GotoUnless(a->WordEqual(exec_result, a->NullConstant()), &next); |
- a->Return(a->SmiConstant(-1)); |
- a->Bind(&next); |
+ Label next(this); |
+ GotoUnless(WordEqual(exec_result, NullConstant()), &next); |
+ Return(SmiConstant(-1)); |
+ Bind(&next); |
} |
// Return the index of the match. |
{ |
- CLabel fast_result(a), slow_result(a, CLabel::kDeferred); |
- BranchIfFastRegExpResult(a, context, a->LoadMap(exec_result), &fast_result, |
+ Label fast_result(this), slow_result(this, Label::kDeferred); |
+ BranchIfFastRegExpResult(context, LoadMap(exec_result), &fast_result, |
&slow_result); |
- a->Bind(&fast_result); |
+ Bind(&fast_result); |
{ |
Node* const index = |
- a->LoadObjectField(exec_result, JSRegExpResult::kIndexOffset); |
- a->Return(index); |
+ LoadObjectField(exec_result, JSRegExpResult::kIndexOffset); |
+ Return(index); |
} |
- a->Bind(&slow_result); |
+ Bind(&slow_result); |
{ |
- Node* const name = a->HeapConstant(isolate->factory()->index_string()); |
- Callable getproperty_callable = CodeFactory::GetProperty(a->isolate()); |
+ Node* const name = HeapConstant(isolate->factory()->index_string()); |
+ Callable getproperty_callable = CodeFactory::GetProperty(isolate); |
Node* const index = |
- a->CallStub(getproperty_callable, context, exec_result, name); |
- a->Return(index); |
+ CallStub(getproperty_callable, context, exec_result, name); |
+ Return(index); |
} |
} |
} |
-} // namespace |
- |
// ES#sec-regexp.prototype-@@search |
// RegExp.prototype [ @@search ] ( string ) |
TF_BUILTIN(RegExpPrototypeSearch, RegExpBuiltinsAssembler) { |
- Isolate* const isolate = this->isolate(); |
- |
Node* const maybe_receiver = Parameter(0); |
Node* const maybe_string = Parameter(1); |
Node* const context = Parameter(4); |
// Ensure {maybe_receiver} is a JSReceiver. |
- Node* const map = |
- ThrowIfNotJSReceiver(this, isolate, context, maybe_receiver, |
- MessageTemplate::kIncompatibleMethodReceiver, |
- "RegExp.prototype.@@search"); |
+ Node* const map = ThrowIfNotJSReceiver( |
+ context, maybe_receiver, MessageTemplate::kIncompatibleMethodReceiver, |
+ "RegExp.prototype.@@search"); |
Node* const receiver = maybe_receiver; |
// Convert {maybe_string} to a String. |
Node* const string = ToString(context, maybe_string); |
- CLabel fast_path(this), slow_path(this); |
- BranchIfFastPath(this, context, map, &fast_path, &slow_path); |
+ Label fast_path(this), slow_path(this); |
+ BranchIfFastRegExp(context, map, &fast_path, &slow_path); |
Bind(&fast_path); |
- RegExpPrototypeSearchBodyFast(this, receiver, string, context); |
+ RegExpPrototypeSearchBodyFast(context, receiver, string); |
Bind(&slow_path); |
- RegExpPrototypeSearchBodySlow(this, receiver, string, context); |
+ RegExpPrototypeSearchBodySlow(context, receiver, string); |
} |
-namespace { |
- |
// Generates the fast path for @@split. {regexp} is an unmodified JSRegExp, |
// {string} is a String, and {limit} is a Smi. |
-void Generate_RegExpPrototypeSplitBody(CodeStubAssembler* a, Node* const regexp, |
- Node* const string, Node* const limit, |
- Node* const context) { |
- Isolate* isolate = a->isolate(); |
+void RegExpBuiltinsAssembler::RegExpPrototypeSplitBody(Node* const context, |
+ Node* const regexp, |
+ Node* const string, |
+ Node* const limit) { |
+ Isolate* isolate = this->isolate(); |
- Node* const null = a->NullConstant(); |
- Node* const smi_zero = a->SmiConstant(0); |
- Node* const int_zero = a->IntPtrConstant(0); |
- Node* const int_limit = a->SmiUntag(limit); |
+ Node* const null = NullConstant(); |
+ Node* const smi_zero = SmiConstant(0); |
+ Node* const int_zero = IntPtrConstant(0); |
+ Node* const int_limit = SmiUntag(limit); |
const ElementsKind kind = FAST_ELEMENTS; |
const ParameterMode mode = CodeStubAssembler::INTPTR_PARAMETERS; |
Node* const allocation_site = nullptr; |
- Node* const native_context = a->LoadNativeContext(context); |
- Node* const array_map = a->LoadJSArrayElementsMap(kind, native_context); |
+ Node* const native_context = LoadNativeContext(context); |
+ Node* const array_map = LoadJSArrayElementsMap(kind, native_context); |
- CLabel return_empty_array(a, CLabel::kDeferred); |
+ Label return_empty_array(this, Label::kDeferred); |
// If limit is zero, return an empty array. |
{ |
- CLabel next(a), if_limitiszero(a, CLabel::kDeferred); |
- a->Branch(a->SmiEqual(limit, smi_zero), &return_empty_array, &next); |
- a->Bind(&next); |
+ Label next(this), if_limitiszero(this, Label::kDeferred); |
+ Branch(SmiEqual(limit, smi_zero), &return_empty_array, &next); |
+ Bind(&next); |
} |
- Node* const string_length = a->LoadStringLength(string); |
+ Node* const string_length = LoadStringLength(string); |
// If passed the empty {string}, return either an empty array or a singleton |
// array depending on whether the {regexp} matches. |
{ |
- CLabel next(a), if_stringisempty(a, CLabel::kDeferred); |
- a->Branch(a->SmiEqual(string_length, smi_zero), &if_stringisempty, &next); |
+ Label next(this), if_stringisempty(this, Label::kDeferred); |
+ Branch(SmiEqual(string_length, smi_zero), &if_stringisempty, &next); |
- a->Bind(&if_stringisempty); |
+ Bind(&if_stringisempty); |
{ |
- Node* const last_match_info = a->LoadContextElement( |
+ Node* const last_match_info = LoadContextElement( |
native_context, Context::REGEXP_LAST_MATCH_INFO_INDEX); |
Callable exec_callable = CodeFactory::RegExpExec(isolate); |
- Node* const match_indices = a->CallStub( |
- exec_callable, context, regexp, string, smi_zero, last_match_info); |
+ Node* const match_indices = CallStub(exec_callable, context, regexp, |
+ string, smi_zero, last_match_info); |
- CLabel return_singleton_array(a); |
- a->Branch(a->WordEqual(match_indices, null), &return_singleton_array, |
- &return_empty_array); |
+ Label return_singleton_array(this); |
+ Branch(WordEqual(match_indices, null), &return_singleton_array, |
+ &return_empty_array); |
- a->Bind(&return_singleton_array); |
+ Bind(&return_singleton_array); |
{ |
- Node* const length = a->SmiConstant(1); |
- Node* const capacity = a->IntPtrConstant(1); |
- Node* const result = a->AllocateJSArray(kind, array_map, capacity, |
- length, allocation_site, mode); |
+ Node* const length = SmiConstant(1); |
+ Node* const capacity = IntPtrConstant(1); |
+ Node* const result = AllocateJSArray(kind, array_map, capacity, length, |
+ allocation_site, mode); |
- Node* const fixed_array = a->LoadElements(result); |
- a->StoreFixedArrayElement(fixed_array, 0, string); |
+ Node* const fixed_array = LoadElements(result); |
+ StoreFixedArrayElement(fixed_array, 0, string); |
- a->Return(result); |
+ Return(result); |
} |
} |
- a->Bind(&next); |
+ Bind(&next); |
} |
// Loop preparations. |
- GrowableFixedArray array(a); |
+ GrowableFixedArray array(this); |
- CVariable var_last_matched_until(a, MachineRepresentation::kTagged); |
- CVariable var_next_search_from(a, MachineRepresentation::kTagged); |
+ Variable var_last_matched_until(this, MachineRepresentation::kTagged); |
+ Variable var_next_search_from(this, MachineRepresentation::kTagged); |
var_last_matched_until.Bind(smi_zero); |
var_next_search_from.Bind(smi_zero); |
- CVariable* vars[] = {array.var_array(), array.var_length(), |
- array.var_capacity(), &var_last_matched_until, |
- &var_next_search_from}; |
+ Variable* vars[] = {array.var_array(), array.var_length(), |
+ array.var_capacity(), &var_last_matched_until, |
+ &var_next_search_from}; |
const int vars_count = sizeof(vars) / sizeof(vars[0]); |
- CLabel loop(a, vars_count, vars), push_suffix_and_out(a), out(a); |
- a->Goto(&loop); |
+ Label loop(this, vars_count, vars), push_suffix_and_out(this), out(this); |
+ Goto(&loop); |
- a->Bind(&loop); |
+ Bind(&loop); |
{ |
Node* const next_search_from = var_next_search_from.value(); |
Node* const last_matched_until = var_last_matched_until.value(); |
// We're done if we've reached the end of the string. |
{ |
- CLabel next(a); |
- a->Branch(a->SmiEqual(next_search_from, string_length), |
- &push_suffix_and_out, &next); |
- a->Bind(&next); |
+ Label next(this); |
+ Branch(SmiEqual(next_search_from, string_length), &push_suffix_and_out, |
+ &next); |
+ Bind(&next); |
} |
// Search for the given {regexp}. |
- Node* const last_match_info = a->LoadContextElement( |
+ Node* const last_match_info = LoadContextElement( |
native_context, Context::REGEXP_LAST_MATCH_INFO_INDEX); |
Callable exec_callable = CodeFactory::RegExpExec(isolate); |
- Node* const match_indices = |
- a->CallStub(exec_callable, context, regexp, string, next_search_from, |
- last_match_info); |
+ Node* const match_indices = CallStub(exec_callable, context, regexp, string, |
+ next_search_from, last_match_info); |
// We're done if no match was found. |
{ |
- CLabel next(a); |
- a->Branch(a->WordEqual(match_indices, null), &push_suffix_and_out, &next); |
- a->Bind(&next); |
+ Label next(this); |
+ Branch(WordEqual(match_indices, null), &push_suffix_and_out, &next); |
+ Bind(&next); |
} |
- Node* const match_from = a->LoadFixedArrayElement( |
+ Node* const match_from = LoadFixedArrayElement( |
match_indices, RegExpMatchInfo::kFirstCaptureIndex); |
// We're done if the match starts beyond the string. |
{ |
- CLabel next(a); |
- a->Branch(a->WordEqual(match_from, string_length), &push_suffix_and_out, |
- &next); |
- a->Bind(&next); |
+ Label next(this); |
+ Branch(WordEqual(match_from, string_length), &push_suffix_and_out, &next); |
+ Bind(&next); |
} |
- Node* const match_to = a->LoadFixedArrayElement( |
+ Node* const match_to = LoadFixedArrayElement( |
match_indices, RegExpMatchInfo::kFirstCaptureIndex + 1); |
// Advance index and continue if the match is empty. |
{ |
- CLabel next(a); |
+ Label next(this); |
- a->GotoUnless(a->SmiEqual(match_to, next_search_from), &next); |
- a->GotoUnless(a->SmiEqual(match_to, last_matched_until), &next); |
+ GotoUnless(SmiEqual(match_to, next_search_from), &next); |
+ GotoUnless(SmiEqual(match_to, last_matched_until), &next); |
- Node* const is_unicode = FastFlagGetter(a, regexp, JSRegExp::kUnicode); |
+ Node* const is_unicode = FastFlagGetter(regexp, JSRegExp::kUnicode); |
Node* const new_next_search_from = |
- AdvanceStringIndex(a, string, next_search_from, is_unicode); |
+ AdvanceStringIndex(string, next_search_from, is_unicode); |
var_next_search_from.Bind(new_next_search_from); |
- a->Goto(&loop); |
+ Goto(&loop); |
- a->Bind(&next); |
+ Bind(&next); |
} |
// A valid match was found, add the new substring to the array. |
@@ -1911,114 +1928,108 @@ void Generate_RegExpPrototypeSplitBody(CodeStubAssembler* a, Node* const regexp, |
Node* const from = last_matched_until; |
Node* const to = match_from; |
- Node* const substr = a->SubString(context, string, from, to); |
+ Node* const substr = SubString(context, string, from, to); |
array.Push(substr); |
- a->GotoIf(a->WordEqual(array.length(), int_limit), &out); |
+ GotoIf(WordEqual(array.length(), int_limit), &out); |
} |
// Add all captures to the array. |
{ |
- Node* const num_registers = a->LoadFixedArrayElement( |
+ Node* const num_registers = LoadFixedArrayElement( |
match_indices, RegExpMatchInfo::kNumberOfCapturesIndex); |
- Node* const int_num_registers = a->SmiUntag(num_registers); |
+ Node* const int_num_registers = SmiUntag(num_registers); |
- CVariable var_reg(a, MachineType::PointerRepresentation()); |
- var_reg.Bind(a->IntPtrConstant(2)); |
+ Variable var_reg(this, MachineType::PointerRepresentation()); |
+ var_reg.Bind(IntPtrConstant(2)); |
- CVariable* vars[] = {array.var_array(), array.var_length(), |
- array.var_capacity(), &var_reg}; |
+ Variable* vars[] = {array.var_array(), array.var_length(), |
+ array.var_capacity(), &var_reg}; |
const int vars_count = sizeof(vars) / sizeof(vars[0]); |
- CLabel nested_loop(a, vars_count, vars), nested_loop_out(a); |
- a->Branch(a->IntPtrLessThan(var_reg.value(), int_num_registers), |
- &nested_loop, &nested_loop_out); |
+ Label nested_loop(this, vars_count, vars), nested_loop_out(this); |
+ Branch(IntPtrLessThan(var_reg.value(), int_num_registers), &nested_loop, |
+ &nested_loop_out); |
- a->Bind(&nested_loop); |
+ Bind(&nested_loop); |
{ |
Node* const reg = var_reg.value(); |
- Node* const from = a->LoadFixedArrayElement( |
+ Node* const from = LoadFixedArrayElement( |
match_indices, reg, |
RegExpMatchInfo::kFirstCaptureIndex * kPointerSize, mode); |
- Node* const to = a->LoadFixedArrayElement( |
+ Node* const to = LoadFixedArrayElement( |
match_indices, reg, |
(RegExpMatchInfo::kFirstCaptureIndex + 1) * kPointerSize, mode); |
- CLabel select_capture(a), select_undefined(a), store_value(a); |
- CVariable var_value(a, MachineRepresentation::kTagged); |
- a->Branch(a->SmiEqual(to, a->SmiConstant(-1)), &select_undefined, |
- &select_capture); |
+ Label select_capture(this), select_undefined(this), store_value(this); |
+ Variable var_value(this, MachineRepresentation::kTagged); |
+ Branch(SmiEqual(to, SmiConstant(-1)), &select_undefined, |
+ &select_capture); |
- a->Bind(&select_capture); |
+ Bind(&select_capture); |
{ |
- Node* const substr = a->SubString(context, string, from, to); |
+ Node* const substr = SubString(context, string, from, to); |
var_value.Bind(substr); |
- a->Goto(&store_value); |
+ Goto(&store_value); |
} |
- a->Bind(&select_undefined); |
+ Bind(&select_undefined); |
{ |
- Node* const undefined = a->UndefinedConstant(); |
+ Node* const undefined = UndefinedConstant(); |
var_value.Bind(undefined); |
- a->Goto(&store_value); |
+ Goto(&store_value); |
} |
- a->Bind(&store_value); |
+ Bind(&store_value); |
{ |
array.Push(var_value.value()); |
- a->GotoIf(a->WordEqual(array.length(), int_limit), &out); |
+ GotoIf(WordEqual(array.length(), int_limit), &out); |
- Node* const new_reg = a->IntPtrAdd(reg, a->IntPtrConstant(2)); |
+ Node* const new_reg = IntPtrAdd(reg, IntPtrConstant(2)); |
var_reg.Bind(new_reg); |
- a->Branch(a->IntPtrLessThan(new_reg, int_num_registers), &nested_loop, |
- &nested_loop_out); |
+ Branch(IntPtrLessThan(new_reg, int_num_registers), &nested_loop, |
+ &nested_loop_out); |
} |
} |
- a->Bind(&nested_loop_out); |
+ Bind(&nested_loop_out); |
} |
var_last_matched_until.Bind(match_to); |
var_next_search_from.Bind(match_to); |
- a->Goto(&loop); |
+ Goto(&loop); |
} |
- a->Bind(&push_suffix_and_out); |
+ Bind(&push_suffix_and_out); |
{ |
Node* const from = var_last_matched_until.value(); |
Node* const to = string_length; |
- Node* const substr = a->SubString(context, string, from, to); |
+ Node* const substr = SubString(context, string, from, to); |
array.Push(substr); |
- a->Goto(&out); |
+ Goto(&out); |
} |
- a->Bind(&out); |
+ Bind(&out); |
{ |
Node* const result = array.ToJSArray(context); |
- a->Return(result); |
+ Return(result); |
} |
- a->Bind(&return_empty_array); |
+ Bind(&return_empty_array); |
{ |
Node* const length = smi_zero; |
Node* const capacity = int_zero; |
- Node* const result = a->AllocateJSArray(kind, array_map, capacity, length, |
- allocation_site, mode); |
- a->Return(result); |
+ Node* const result = AllocateJSArray(kind, array_map, capacity, length, |
+ allocation_site, mode); |
+ Return(result); |
} |
} |
-} // namespace |
- |
// ES#sec-regexp.prototype-@@split |
// RegExp.prototype [ @@split ] ( string, limit ) |
TF_BUILTIN(RegExpPrototypeSplit, RegExpBuiltinsAssembler) { |
- Isolate* const isolate = this->isolate(); |
- |
- Node* const undefined = UndefinedConstant(); |
- |
Node* const maybe_receiver = Parameter(0); |
Node* const maybe_string = Parameter(1); |
Node* const maybe_limit = Parameter(2); |
@@ -2026,23 +2037,27 @@ TF_BUILTIN(RegExpPrototypeSplit, RegExpBuiltinsAssembler) { |
// Ensure {maybe_receiver} is a JSReceiver. |
Node* const map = ThrowIfNotJSReceiver( |
- this, isolate, context, maybe_receiver, |
- MessageTemplate::kIncompatibleMethodReceiver, "RegExp.prototype.@@split"); |
+ context, maybe_receiver, MessageTemplate::kIncompatibleMethodReceiver, |
+ "RegExp.prototype.@@split"); |
Node* const receiver = maybe_receiver; |
// Convert {maybe_string} to a String. |
Node* const string = ToString(context, maybe_string); |
- CLabel fast_path(this), slow_path(this); |
- BranchIfFastPath(this, context, map, &fast_path, &slow_path); |
+ Label fast_path(this), slow_path(this); |
+ BranchIfFastRegExp(context, map, &fast_path, &slow_path); |
Bind(&fast_path); |
{ |
+ // TODO(jgruber): Even if map checks send us to the fast path, we still need |
+ // to verify the constructor property and jump to the slow path if it has |
+ // been changed. |
+ |
// Convert {maybe_limit} to a uint32, capping at the maximal smi value. |
- CVariable var_limit(this, MachineRepresentation::kTagged); |
- CLabel if_limitissmimax(this), limit_done(this); |
+ Variable var_limit(this, MachineRepresentation::kTagged); |
+ Label if_limitissmimax(this), limit_done(this); |
- GotoIf(WordEqual(maybe_limit, undefined), &if_limitissmimax); |
+ GotoIf(IsUndefined(maybe_limit), &if_limitissmimax); |
{ |
Node* const limit = ToUint32(context, maybe_limit); |
@@ -2064,7 +2079,7 @@ TF_BUILTIN(RegExpPrototypeSplit, RegExpBuiltinsAssembler) { |
Bind(&limit_done); |
{ |
Node* const limit = var_limit.value(); |
- Generate_RegExpPrototypeSplitBody(this, receiver, string, limit, context); |
+ RegExpPrototypeSplitBody(context, receiver, string, limit); |
} |
} |
@@ -2076,74 +2091,71 @@ TF_BUILTIN(RegExpPrototypeSplit, RegExpBuiltinsAssembler) { |
} |
} |
-namespace { |
- |
-Node* ReplaceGlobalCallableFastPath(CodeStubAssembler* a, Node* context, |
- Node* regexp, Node* subject_string, |
- Node* replace_callable) { |
+Node* RegExpBuiltinsAssembler::ReplaceGlobalCallableFastPath( |
+ Node* context, Node* regexp, Node* string, Node* replace_callable) { |
// The fast path is reached only if {receiver} is a global unmodified |
// JSRegExp instance and {replace_callable} is callable. |
- Isolate* const isolate = a->isolate(); |
+ Isolate* const isolate = this->isolate(); |
- Node* const null = a->NullConstant(); |
- Node* const undefined = a->UndefinedConstant(); |
- Node* const int_zero = a->IntPtrConstant(0); |
- Node* const int_one = a->IntPtrConstant(1); |
- Node* const smi_zero = a->SmiConstant(Smi::kZero); |
+ Node* const null = NullConstant(); |
+ Node* const undefined = UndefinedConstant(); |
+ Node* const int_zero = IntPtrConstant(0); |
+ Node* const int_one = IntPtrConstant(1); |
+ Node* const smi_zero = SmiConstant(Smi::kZero); |
- Node* const native_context = a->LoadNativeContext(context); |
+ Node* const native_context = LoadNativeContext(context); |
- CLabel out(a); |
- CVariable var_result(a, MachineRepresentation::kTagged); |
+ Label out(this); |
+ Variable var_result(this, MachineRepresentation::kTagged); |
// Set last index to 0. |
- FastStoreLastIndex(a, regexp, smi_zero); |
+ FastStoreLastIndex(regexp, smi_zero); |
// Allocate {result_array}. |
Node* result_array; |
{ |
ElementsKind kind = FAST_ELEMENTS; |
- Node* const array_map = a->LoadJSArrayElementsMap(kind, native_context); |
- Node* const capacity = a->IntPtrConstant(16); |
+ Node* const array_map = LoadJSArrayElementsMap(kind, native_context); |
+ Node* const capacity = IntPtrConstant(16); |
Node* const length = smi_zero; |
Node* const allocation_site = nullptr; |
ParameterMode capacity_mode = CodeStubAssembler::INTPTR_PARAMETERS; |
- result_array = a->AllocateJSArray(kind, array_map, capacity, length, |
- allocation_site, capacity_mode); |
+ result_array = AllocateJSArray(kind, array_map, capacity, length, |
+ allocation_site, capacity_mode); |
} |
// Call into runtime for RegExpExecMultiple. |
- Node* last_match_info = a->LoadContextElement( |
- native_context, Context::REGEXP_LAST_MATCH_INFO_INDEX); |
- Node* const res = |
- a->CallRuntime(Runtime::kRegExpExecMultiple, context, regexp, |
- subject_string, last_match_info, result_array); |
+ Node* last_match_info = |
+ LoadContextElement(native_context, Context::REGEXP_LAST_MATCH_INFO_INDEX); |
+ Node* const res = CallRuntime(Runtime::kRegExpExecMultiple, context, regexp, |
+ string, last_match_info, result_array); |
// Reset last index to 0. |
- FastStoreLastIndex(a, regexp, smi_zero); |
+ FastStoreLastIndex(regexp, smi_zero); |
// If no matches, return the subject string. |
- var_result.Bind(subject_string); |
- a->GotoIf(a->WordEqual(res, null), &out); |
+ var_result.Bind(string); |
+ GotoIf(WordEqual(res, null), &out); |
// Reload last match info since it might have changed. |
- last_match_info = a->LoadContextElement( |
- native_context, Context::REGEXP_LAST_MATCH_INFO_INDEX); |
+ last_match_info = |
+ LoadContextElement(native_context, Context::REGEXP_LAST_MATCH_INFO_INDEX); |
- Node* const res_length = a->LoadJSArrayLength(res); |
- Node* const res_elems = a->LoadElements(res); |
- CSA_ASSERT(a, a->HasInstanceType(res_elems, FIXED_ARRAY_TYPE)); |
+ Node* const res_length = LoadJSArrayLength(res); |
+ Node* const res_elems = LoadElements(res); |
+ CSA_ASSERT(this, HasInstanceType(res_elems, FIXED_ARRAY_TYPE)); |
- Node* const num_capture_registers = a->LoadFixedArrayElement( |
+ Node* const num_capture_registers = LoadFixedArrayElement( |
last_match_info, RegExpMatchInfo::kNumberOfCapturesIndex); |
- CLabel if_hasexplicitcaptures(a), if_noexplicitcaptures(a), create_result(a); |
- a->Branch(a->SmiEqual(num_capture_registers, a->SmiConstant(Smi::FromInt(2))), |
- &if_noexplicitcaptures, &if_hasexplicitcaptures); |
+ Label if_hasexplicitcaptures(this), if_noexplicitcaptures(this), |
+ create_result(this); |
+ Branch(SmiEqual(num_capture_registers, SmiConstant(Smi::FromInt(2))), |
+ &if_noexplicitcaptures, &if_hasexplicitcaptures); |
- a->Bind(&if_noexplicitcaptures); |
+ Bind(&if_noexplicitcaptures); |
{ |
// If the number of captures is two then there are no explicit captures in |
// the regexp, just the implicit capture that captures the whole match. In |
@@ -2152,260 +2164,253 @@ Node* ReplaceGlobalCallableFastPath(CodeStubAssembler* a, Node* context, |
// input string and some replacements that were returned from the replace |
// function. |
- CVariable var_match_start(a, MachineRepresentation::kTagged); |
+ Variable var_match_start(this, MachineRepresentation::kTagged); |
var_match_start.Bind(smi_zero); |
- Node* const end = a->SmiUntag(res_length); |
- CVariable var_i(a, MachineType::PointerRepresentation()); |
+ Node* const end = SmiUntag(res_length); |
+ Variable var_i(this, MachineType::PointerRepresentation()); |
var_i.Bind(int_zero); |
- CVariable* vars[] = {&var_i, &var_match_start}; |
- CLabel loop(a, 2, vars); |
- a->Goto(&loop); |
- a->Bind(&loop); |
+ Variable* vars[] = {&var_i, &var_match_start}; |
+ Label loop(this, 2, vars); |
+ Goto(&loop); |
+ Bind(&loop); |
{ |
Node* const i = var_i.value(); |
- a->GotoUnless(a->IntPtrLessThan(i, end), &create_result); |
+ GotoUnless(IntPtrLessThan(i, end), &create_result); |
ParameterMode mode = CodeStubAssembler::INTPTR_PARAMETERS; |
- Node* const elem = a->LoadFixedArrayElement(res_elems, i, 0, mode); |
+ Node* const elem = LoadFixedArrayElement(res_elems, i, 0, mode); |
- CLabel if_issmi(a), if_isstring(a), loop_epilogue(a); |
- a->Branch(a->TaggedIsSmi(elem), &if_issmi, &if_isstring); |
+ Label if_issmi(this), if_isstring(this), loop_epilogue(this); |
+ Branch(TaggedIsSmi(elem), &if_issmi, &if_isstring); |
- a->Bind(&if_issmi); |
+ Bind(&if_issmi); |
{ |
// Integers represent slices of the original string. |
- CLabel if_isnegativeorzero(a), if_ispositive(a); |
- a->BranchIfSmiLessThanOrEqual(elem, smi_zero, &if_isnegativeorzero, |
- &if_ispositive); |
+ Label if_isnegativeorzero(this), if_ispositive(this); |
+ BranchIfSmiLessThanOrEqual(elem, smi_zero, &if_isnegativeorzero, |
+ &if_ispositive); |
- a->Bind(&if_ispositive); |
+ Bind(&if_ispositive); |
{ |
- Node* const int_elem = a->SmiUntag(elem); |
+ Node* const int_elem = SmiUntag(elem); |
Node* const new_match_start = |
- a->IntPtrAdd(a->WordShr(int_elem, a->IntPtrConstant(11)), |
- a->WordAnd(int_elem, a->IntPtrConstant(0x7ff))); |
- var_match_start.Bind(a->SmiTag(new_match_start)); |
- a->Goto(&loop_epilogue); |
+ IntPtrAdd(WordShr(int_elem, IntPtrConstant(11)), |
+ WordAnd(int_elem, IntPtrConstant(0x7ff))); |
+ var_match_start.Bind(SmiTag(new_match_start)); |
+ Goto(&loop_epilogue); |
} |
- a->Bind(&if_isnegativeorzero); |
+ Bind(&if_isnegativeorzero); |
{ |
- Node* const next_i = a->IntPtrAdd(i, int_one); |
+ Node* const next_i = IntPtrAdd(i, int_one); |
var_i.Bind(next_i); |
Node* const next_elem = |
- a->LoadFixedArrayElement(res_elems, next_i, 0, mode); |
+ LoadFixedArrayElement(res_elems, next_i, 0, mode); |
- Node* const new_match_start = a->SmiSub(next_elem, elem); |
+ Node* const new_match_start = SmiSub(next_elem, elem); |
var_match_start.Bind(new_match_start); |
- a->Goto(&loop_epilogue); |
+ Goto(&loop_epilogue); |
} |
} |
- a->Bind(&if_isstring); |
+ Bind(&if_isstring); |
{ |
- CSA_ASSERT(a, a->IsStringInstanceType(a->LoadInstanceType(elem))); |
+ CSA_ASSERT(this, IsStringInstanceType(LoadInstanceType(elem))); |
Callable call_callable = CodeFactory::Call(isolate); |
Node* const replacement_obj = |
- a->CallJS(call_callable, context, replace_callable, undefined, elem, |
- var_match_start.value(), subject_string); |
+ CallJS(call_callable, context, replace_callable, undefined, elem, |
+ var_match_start.value(), string); |
- Node* const replacement_str = a->ToString(context, replacement_obj); |
- a->StoreFixedArrayElement(res_elems, i, replacement_str); |
+ Node* const replacement_str = ToString(context, replacement_obj); |
+ StoreFixedArrayElement(res_elems, i, replacement_str); |
- Node* const elem_length = a->LoadStringLength(elem); |
+ Node* const elem_length = LoadStringLength(elem); |
Node* const new_match_start = |
- a->SmiAdd(var_match_start.value(), elem_length); |
+ SmiAdd(var_match_start.value(), elem_length); |
var_match_start.Bind(new_match_start); |
- a->Goto(&loop_epilogue); |
+ Goto(&loop_epilogue); |
} |
- a->Bind(&loop_epilogue); |
+ Bind(&loop_epilogue); |
{ |
- var_i.Bind(a->IntPtrAdd(var_i.value(), int_one)); |
- a->Goto(&loop); |
+ var_i.Bind(IntPtrAdd(var_i.value(), int_one)); |
+ Goto(&loop); |
} |
} |
} |
- a->Bind(&if_hasexplicitcaptures); |
+ Bind(&if_hasexplicitcaptures); |
{ |
ParameterMode mode = CodeStubAssembler::INTPTR_PARAMETERS; |
Node* const from = int_zero; |
- Node* const to = a->SmiUntag(res_length); |
+ Node* const to = SmiUntag(res_length); |
const int increment = 1; |
- a->BuildFastLoop( |
+ BuildFastLoop( |
MachineType::PointerRepresentation(), from, to, |
- [a, res_elems, isolate, native_context, context, undefined, |
+ [this, res_elems, isolate, native_context, context, undefined, |
replace_callable, mode](Node* index) { |
- Node* const elem = |
- a->LoadFixedArrayElement(res_elems, index, 0, mode); |
+ Node* const elem = LoadFixedArrayElement(res_elems, index, 0, mode); |
- CLabel do_continue(a); |
- a->GotoIf(a->TaggedIsSmi(elem), &do_continue); |
+ Label do_continue(this); |
+ GotoIf(TaggedIsSmi(elem), &do_continue); |
// elem must be an Array. |
// Use the apply argument as backing for global RegExp properties. |
- CSA_ASSERT(a, a->HasInstanceType(elem, JS_ARRAY_TYPE)); |
+ CSA_ASSERT(this, HasInstanceType(elem, JS_ARRAY_TYPE)); |
// TODO(jgruber): Remove indirection through Call->ReflectApply. |
Callable call_callable = CodeFactory::Call(isolate); |
- Node* const reflect_apply = a->LoadContextElement( |
- native_context, Context::REFLECT_APPLY_INDEX); |
+ Node* const reflect_apply = |
+ LoadContextElement(native_context, Context::REFLECT_APPLY_INDEX); |
Node* const replacement_obj = |
- a->CallJS(call_callable, context, reflect_apply, undefined, |
- replace_callable, undefined, elem); |
+ CallJS(call_callable, context, reflect_apply, undefined, |
+ replace_callable, undefined, elem); |
// Overwrite the i'th element in the results with the string we got |
// back from the callback function. |
- Node* const replacement_str = a->ToString(context, replacement_obj); |
- a->StoreFixedArrayElement(res_elems, index, replacement_str, |
- UPDATE_WRITE_BARRIER, 0, mode); |
+ Node* const replacement_str = ToString(context, replacement_obj); |
+ StoreFixedArrayElement(res_elems, index, replacement_str, |
+ UPDATE_WRITE_BARRIER, 0, mode); |
- a->Goto(&do_continue); |
- a->Bind(&do_continue); |
+ Goto(&do_continue); |
+ Bind(&do_continue); |
}, |
increment, CodeStubAssembler::IndexAdvanceMode::kPost); |
- a->Goto(&create_result); |
+ Goto(&create_result); |
} |
- a->Bind(&create_result); |
+ Bind(&create_result); |
{ |
- Node* const result = a->CallRuntime(Runtime::kStringBuilderConcat, context, |
- res, res_length, subject_string); |
+ Node* const result = CallRuntime(Runtime::kStringBuilderConcat, context, |
+ res, res_length, string); |
var_result.Bind(result); |
- a->Goto(&out); |
+ Goto(&out); |
} |
- a->Bind(&out); |
+ Bind(&out); |
return var_result.value(); |
} |
-Node* ReplaceSimpleStringFastPath(CodeStubAssembler* a, Node* context, |
- Node* regexp, Node* subject_string, |
- Node* replace_string) { |
+Node* RegExpBuiltinsAssembler::ReplaceSimpleStringFastPath( |
+ Node* context, Node* regexp, Node* string, Node* replace_string) { |
// The fast path is reached only if {receiver} is an unmodified |
// JSRegExp instance, {replace_value} is non-callable, and |
// ToString({replace_value}) does not contain '$', i.e. we're doing a simple |
// string replacement. |
- Isolate* const isolate = a->isolate(); |
+ Isolate* const isolate = this->isolate(); |
- Node* const null = a->NullConstant(); |
- Node* const int_zero = a->IntPtrConstant(0); |
- Node* const smi_zero = a->SmiConstant(Smi::kZero); |
+ Node* const null = NullConstant(); |
+ Node* const int_zero = IntPtrConstant(0); |
+ Node* const smi_zero = SmiConstant(Smi::kZero); |
- CLabel out(a); |
- CVariable var_result(a, MachineRepresentation::kTagged); |
+ Label out(this); |
+ Variable var_result(this, MachineRepresentation::kTagged); |
// Load the last match info. |
- Node* const native_context = a->LoadNativeContext(context); |
- Node* const last_match_info = a->LoadContextElement( |
- native_context, Context::REGEXP_LAST_MATCH_INFO_INDEX); |
+ Node* const native_context = LoadNativeContext(context); |
+ Node* const last_match_info = |
+ LoadContextElement(native_context, Context::REGEXP_LAST_MATCH_INFO_INDEX); |
// Is {regexp} global? |
- CLabel if_isglobal(a), if_isnonglobal(a); |
- Node* const flags = a->LoadObjectField(regexp, JSRegExp::kFlagsOffset); |
+ Label if_isglobal(this), if_isnonglobal(this); |
+ Node* const flags = LoadObjectField(regexp, JSRegExp::kFlagsOffset); |
Node* const is_global = |
- a->WordAnd(a->SmiUntag(flags), a->IntPtrConstant(JSRegExp::kGlobal)); |
- a->Branch(a->WordEqual(is_global, int_zero), &if_isnonglobal, &if_isglobal); |
+ WordAnd(SmiUntag(flags), IntPtrConstant(JSRegExp::kGlobal)); |
+ Branch(WordEqual(is_global, int_zero), &if_isnonglobal, &if_isglobal); |
- a->Bind(&if_isglobal); |
+ Bind(&if_isglobal); |
{ |
// Hand off global regexps to runtime. |
- FastStoreLastIndex(a, regexp, smi_zero); |
+ FastStoreLastIndex(regexp, smi_zero); |
Node* const result = |
- a->CallRuntime(Runtime::kStringReplaceGlobalRegExpWithString, context, |
- subject_string, regexp, replace_string, last_match_info); |
+ CallRuntime(Runtime::kStringReplaceGlobalRegExpWithString, context, |
+ string, regexp, replace_string, last_match_info); |
var_result.Bind(result); |
- a->Goto(&out); |
+ Goto(&out); |
} |
- a->Bind(&if_isnonglobal); |
+ Bind(&if_isnonglobal); |
{ |
// Run exec, then manually construct the resulting string. |
Callable exec_callable = CodeFactory::RegExpExec(isolate); |
- Node* const match_indices = |
- a->CallStub(exec_callable, context, regexp, subject_string, smi_zero, |
- last_match_info); |
+ Node* const match_indices = CallStub(exec_callable, context, regexp, string, |
+ smi_zero, last_match_info); |
- CLabel if_matched(a), if_didnotmatch(a); |
- a->Branch(a->WordEqual(match_indices, null), &if_didnotmatch, &if_matched); |
+ Label if_matched(this), if_didnotmatch(this); |
+ Branch(WordEqual(match_indices, null), &if_didnotmatch, &if_matched); |
- a->Bind(&if_didnotmatch); |
+ Bind(&if_didnotmatch); |
{ |
- FastStoreLastIndex(a, regexp, smi_zero); |
- var_result.Bind(subject_string); |
- a->Goto(&out); |
+ FastStoreLastIndex(regexp, smi_zero); |
+ var_result.Bind(string); |
+ Goto(&out); |
} |
- a->Bind(&if_matched); |
+ Bind(&if_matched); |
{ |
Node* const subject_start = smi_zero; |
- Node* const match_start = a->LoadFixedArrayElement( |
+ Node* const match_start = LoadFixedArrayElement( |
match_indices, RegExpMatchInfo::kFirstCaptureIndex); |
- Node* const match_end = a->LoadFixedArrayElement( |
+ Node* const match_end = LoadFixedArrayElement( |
match_indices, RegExpMatchInfo::kFirstCaptureIndex + 1); |
- Node* const subject_end = a->LoadStringLength(subject_string); |
+ Node* const subject_end = LoadStringLength(string); |
- CLabel if_replaceisempty(a), if_replaceisnotempty(a); |
- Node* const replace_length = a->LoadStringLength(replace_string); |
- a->Branch(a->SmiEqual(replace_length, smi_zero), &if_replaceisempty, |
- &if_replaceisnotempty); |
+ Label if_replaceisempty(this), if_replaceisnotempty(this); |
+ Node* const replace_length = LoadStringLength(replace_string); |
+ Branch(SmiEqual(replace_length, smi_zero), &if_replaceisempty, |
+ &if_replaceisnotempty); |
- a->Bind(&if_replaceisempty); |
+ Bind(&if_replaceisempty); |
{ |
// TODO(jgruber): We could skip many of the checks that using SubString |
// here entails. |
Node* const first_part = |
- a->SubString(context, subject_string, subject_start, match_start); |
+ SubString(context, string, subject_start, match_start); |
Node* const second_part = |
- a->SubString(context, subject_string, match_end, subject_end); |
+ SubString(context, string, match_end, subject_end); |
- Node* const result = a->StringAdd(context, first_part, second_part); |
+ Node* const result = StringAdd(context, first_part, second_part); |
var_result.Bind(result); |
- a->Goto(&out); |
+ Goto(&out); |
} |
- a->Bind(&if_replaceisnotempty); |
+ Bind(&if_replaceisnotempty); |
{ |
Node* const first_part = |
- a->SubString(context, subject_string, subject_start, match_start); |
+ SubString(context, string, subject_start, match_start); |
Node* const second_part = replace_string; |
Node* const third_part = |
- a->SubString(context, subject_string, match_end, subject_end); |
+ SubString(context, string, match_end, subject_end); |
- Node* result = a->StringAdd(context, first_part, second_part); |
- result = a->StringAdd(context, result, third_part); |
+ Node* result = StringAdd(context, first_part, second_part); |
+ result = StringAdd(context, result, third_part); |
var_result.Bind(result); |
- a->Goto(&out); |
+ Goto(&out); |
} |
} |
} |
- a->Bind(&out); |
+ Bind(&out); |
return var_result.value(); |
} |
-} // namespace |
- |
// ES#sec-regexp.prototype-@@replace |
// RegExp.prototype [ @@replace ] ( string, replaceValue ) |
TF_BUILTIN(RegExpPrototypeReplace, RegExpBuiltinsAssembler) { |
- Isolate* const isolate = this->isolate(); |
- |
Node* const maybe_receiver = Parameter(0); |
Node* const maybe_string = Parameter(1); |
Node* const replace_value = Parameter(2); |
@@ -2414,26 +2419,25 @@ TF_BUILTIN(RegExpPrototypeReplace, RegExpBuiltinsAssembler) { |
Node* const int_zero = IntPtrConstant(0); |
// Ensure {maybe_receiver} is a JSReceiver. |
- Node* const map = |
- ThrowIfNotJSReceiver(this, isolate, context, maybe_receiver, |
- MessageTemplate::kIncompatibleMethodReceiver, |
- "RegExp.prototype.@@replace"); |
+ Node* const map = ThrowIfNotJSReceiver( |
+ context, maybe_receiver, MessageTemplate::kIncompatibleMethodReceiver, |
+ "RegExp.prototype.@@replace"); |
Node* const receiver = maybe_receiver; |
// Convert {maybe_string} to a String. |
- Callable tostring_callable = CodeFactory::ToString(isolate); |
+ Callable tostring_callable = CodeFactory::ToString(isolate()); |
Node* const string = CallStub(tostring_callable, context, maybe_string); |
// Fast-path checks: 1. Is the {receiver} an unmodified JSRegExp instance? |
- CLabel checkreplacecallable(this), runtime(this, CLabel::kDeferred), |
+ Label checkreplacecallable(this), runtime(this, Label::kDeferred), |
fastpath(this); |
- BranchIfFastPath(this, context, map, &checkreplacecallable, &runtime); |
+ BranchIfFastRegExp(context, map, &checkreplacecallable, &runtime); |
Bind(&checkreplacecallable); |
Node* const regexp = receiver; |
// 2. Is {replace_value} callable? |
- CLabel checkreplacestring(this), if_iscallable(this); |
+ Label checkreplacestring(this), if_iscallable(this); |
GotoIf(TaggedIsSmi(replace_value), &checkreplacestring); |
Node* const replace_value_map = LoadMap(replace_value); |
@@ -2452,8 +2456,8 @@ TF_BUILTIN(RegExpPrototypeReplace, RegExpBuiltinsAssembler) { |
smi_minusone), |
&runtime); |
- Return(ReplaceSimpleStringFastPath(this, context, regexp, string, |
- replace_string)); |
+ Return( |
+ ReplaceSimpleStringFastPath(context, regexp, string, replace_string)); |
} |
// {regexp} is unmodified and {replace_value} is callable. |
@@ -2462,14 +2466,14 @@ TF_BUILTIN(RegExpPrototypeReplace, RegExpBuiltinsAssembler) { |
Node* const replace_callable = replace_value; |
// Check if the {regexp} is global. |
- CLabel if_isglobal(this), if_isnotglobal(this); |
- Node* const is_global = FastFlagGetter(this, regexp, JSRegExp::kGlobal); |
+ Label if_isglobal(this), if_isnotglobal(this); |
+ Node* const is_global = FastFlagGetter(regexp, JSRegExp::kGlobal); |
Branch(is_global, &if_isglobal, &if_isnotglobal); |
Bind(&if_isglobal); |
{ |
Node* const result = ReplaceGlobalCallableFastPath( |
- this, context, regexp, string, replace_callable); |
+ context, regexp, string, replace_callable); |
Return(result); |
} |
@@ -2493,8 +2497,6 @@ TF_BUILTIN(RegExpPrototypeReplace, RegExpBuiltinsAssembler) { |
// Simple string matching functionality for internal use which does not modify |
// the last match info. |
TF_BUILTIN(RegExpInternalMatch, RegExpBuiltinsAssembler) { |
- Isolate* const isolate = this->isolate(); |
- |
Node* const regexp = Parameter(1); |
Node* const string = Parameter(2); |
Node* const context = Parameter(5); |
@@ -2506,11 +2508,11 @@ TF_BUILTIN(RegExpInternalMatch, RegExpBuiltinsAssembler) { |
Node* const internal_match_info = LoadContextElement( |
native_context, Context::REGEXP_INTERNAL_MATCH_INFO_INDEX); |
- Callable exec_callable = CodeFactory::RegExpExec(isolate); |
+ Callable exec_callable = CodeFactory::RegExpExec(isolate()); |
Node* const match_indices = CallStub(exec_callable, context, regexp, string, |
smi_zero, internal_match_info); |
- CLabel if_matched(this), if_didnotmatch(this); |
+ Label if_matched(this), if_didnotmatch(this); |
Branch(WordEqual(match_indices, null), &if_didnotmatch, &if_matched); |
Bind(&if_didnotmatch); |
@@ -2518,8 +2520,8 @@ TF_BUILTIN(RegExpInternalMatch, RegExpBuiltinsAssembler) { |
Bind(&if_matched); |
{ |
- Node* result = ConstructNewResultFromMatchInfo(isolate, this, context, |
- match_indices, string); |
+ Node* result = |
+ ConstructNewResultFromMatchInfo(context, match_indices, string); |
Return(result); |
} |
} |