// Copyright 2017 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef V8_BUILTINS_BUILTINS_STRING_GEN_H_ #define V8_BUILTINS_BUILTINS_STRING_GEN_H_ #include "src/codegen/code-stub-assembler.h" namespace v8 { namespace internal { class StringBuiltinsAssembler : public CodeStubAssembler { public: explicit StringBuiltinsAssembler(compiler::CodeAssemblerState* state) : CodeStubAssembler(state) {} // ES#sec-getsubstitution Node* GetSubstitution(Node* context, Node* subject_string, Node* match_start_index, Node* match_end_index, Node* replace_string); void StringEqual_Core(SloppyTNode lhs, Node* lhs_instance_type, SloppyTNode rhs, Node* rhs_instance_type, TNode length, Label* if_equal, Label* if_not_equal, Label* if_indirect); void BranchIfStringPrimitiveWithNoCustomIteration(TNode object, TNode context, Label* if_true, Label* if_false); TNode LoadSurrogatePairAt(SloppyTNode string, SloppyTNode length, SloppyTNode index, UnicodeEncoding encoding); TNode StringFromSingleUTF16EncodedCodePoint(TNode codepoint); // Return a new string object which holds a substring containing the range // [from,to[ of string. TNode SubString(TNode string, TNode from, TNode to); // Copies |character_count| elements from |from_string| to |to_string| // starting at the |from_index|'th character. |from_string| and |to_string| // can either be one-byte strings or two-byte strings, although if // |from_string| is two-byte, then |to_string| must be two-byte. // |from_index|, |to_index| and |character_count| must be intptr_ts s.t. 0 <= // |from_index| <= |from_index| + |character_count| <= from_string.length and // 0 <= |to_index| <= |to_index| + |character_count| <= to_string.length. V8_EXPORT_PRIVATE void CopyStringCharacters( Node* from_string, Node* to_string, TNode from_index, TNode to_index, TNode character_count, String::Encoding from_encoding, String::Encoding to_encoding); protected: void StringEqual_Loop(Node* lhs, Node* lhs_instance_type, MachineType lhs_type, Node* rhs, Node* rhs_instance_type, MachineType rhs_type, TNode length, Label* if_equal, Label* if_not_equal); Node* DirectStringData(Node* string, Node* string_instance_type); void DispatchOnStringEncodings(Node* const lhs_instance_type, Node* const rhs_instance_type, Label* if_one_one, Label* if_one_two, Label* if_two_one, Label* if_two_two); template Node* CallSearchStringRaw(Node* const subject_ptr, Node* const subject_length, Node* const search_ptr, Node* const search_length, Node* const start_position); TNode PointerToStringDataAtIndex(TNode string_data, TNode index, String::Encoding encoding); // substr and slice have a common way of handling the {start} argument. void ConvertAndBoundsCheckStartArgument(Node* context, Variable* var_start, Node* start, Node* string_length); void GenerateStringEqual(TNode left, TNode right); void GenerateStringRelationalComparison(TNode left, TNode right, Operation op); using StringAtAccessor = std::function( TNode receiver, TNode length, TNode index)>; void StringIndexOf(TNode const subject_string, TNode const search_string, TNode const position, const std::function)>& f_return); TNode IndexOfDollarChar(Node* const context, Node* const string); TNode StringToArray(TNode context, TNode subject_string, TNode subject_length, TNode limit_number); TNode SmiIsNegative(TNode value) { return SmiLessThan(value, SmiConstant(0)); } TNode AllocateConsString(TNode length, TNode left, TNode right); TNode StringAdd(Node* context, TNode left, TNode right); // Check if |string| is an indirect (thin or flat cons) string type that can // be dereferenced by DerefIndirectString. void BranchIfCanDerefIndirectString(TNode string, TNode instance_type, Label* can_deref, Label* cannot_deref); // Allocate an appropriate one- or two-byte ConsString with the first and // second parts specified by |left| and |right|. // Unpack an indirect (thin or flat cons) string type. void DerefIndirectString(TVariable* var_string, TNode instance_type); // Check if |var_string| has an indirect (thin or flat cons) string type, and // unpack it if so. void MaybeDerefIndirectString(TVariable* var_string, TNode instance_type, Label* did_deref, Label* cannot_deref); // Check if |var_left| or |var_right| has an indirect (thin or flat cons) // string type, and unpack it/them if so. Fall through if nothing was done. void MaybeDerefIndirectStrings(TVariable* var_left, TNode left_instance_type, TVariable* var_right, TNode right_instance_type, Label* did_something); TNode DerefIndirectString(TNode string, TNode instance_type, Label* cannot_deref); // Implements boilerplate logic for {match, split, replace, search} of the // form: // // if (!IS_NULL_OR_UNDEFINED(object)) { // var maybe_function = object[symbol]; // if (!IS_UNDEFINED(maybe_function)) { // return %_Call(maybe_function, ...); // } // } // // Contains fast paths for Smi and RegExp objects. // Important: {regexp_call} may not contain any code that can call into JS. using NodeFunction0 = std::function; using NodeFunction1 = std::function; using DescriptorIndexNameValue = PrototypeCheckAssembler::DescriptorIndexNameValue; void MaybeCallFunctionAtSymbol( Node* const context, Node* const object, Node* const maybe_string, Handle symbol, DescriptorIndexNameValue additional_property_to_check, const NodeFunction0& regexp_call, const NodeFunction1& generic_call); private: TNode AllocAndCopyStringCharacters(Node* from, Node* from_instance_type, TNode from_index, TNode character_count); }; class StringIncludesIndexOfAssembler : public StringBuiltinsAssembler { public: explicit StringIncludesIndexOfAssembler(compiler::CodeAssemblerState* state) : StringBuiltinsAssembler(state) {} protected: enum SearchVariant { kIncludes, kIndexOf }; void Generate(SearchVariant variant, TNode argc, TNode context); }; class StringTrimAssembler : public StringBuiltinsAssembler { public: explicit StringTrimAssembler(compiler::CodeAssemblerState* state) : StringBuiltinsAssembler(state) {} V8_EXPORT_PRIVATE void GotoIfNotWhiteSpaceOrLineTerminator( TNode const char_code, Label* const if_not_whitespace); protected: void Generate(String::TrimMode mode, const char* method, TNode argc, TNode context); void ScanForNonWhiteSpaceOrLineTerminator( Node* const string_data, Node* const string_data_offset, Node* const is_stringonebyte, TVariable* const var_index, TNode const end, int increment, Label* const if_none_found); void BuildLoop(TVariable* const var_index, TNode const end, int increment, Label* const if_none_found, Label* const out, const std::function& get_character); }; } // namespace internal } // namespace v8 #endif // V8_BUILTINS_BUILTINS_STRING_GEN_H_