1 // Copyright 2016 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef V8_CODE_STUB_ASSEMBLER_H_ 6 #define V8_CODE_STUB_ASSEMBLER_H_ 7 8 #include <functional> 9 10 #include "src/base/macros.h" 11 #include "src/compiler/code-assembler.h" 12 #include "src/globals.h" 13 #include "src/objects.h" 14 #include "src/objects/bigint.h" 15 #include "src/roots.h" 16 17 namespace v8 { 18 namespace internal { 19 20 class CallInterfaceDescriptor; 21 class CodeStubArguments; 22 class CodeStubAssembler; 23 class StatsCounter; 24 class StubCache; 25 26 enum class PrimitiveType { kBoolean, kNumber, kString, kSymbol }; 27 28 #define HEAP_MUTABLE_IMMOVABLE_OBJECT_LIST(V) \ 29 V(ArraySpeciesProtector, array_species_protector, ArraySpeciesProtector) \ 30 V(EmptyPropertyDictionary, empty_property_dictionary, \ 31 EmptyPropertyDictionary) \ 32 V(PromiseSpeciesProtector, promise_species_protector, \ 33 PromiseSpeciesProtector) \ 34 V(TypedArraySpeciesProtector, typed_array_species_protector, \ 35 TypedArraySpeciesProtector) \ 36 V(StoreHandler0Map, store_handler0_map, StoreHandler0Map) 37 38 #define HEAP_IMMUTABLE_IMMOVABLE_OBJECT_LIST(V) \ 39 V(AccessorInfoMap, accessor_info_map, AccessorInfoMap) \ 40 V(AccessorPairMap, accessor_pair_map, AccessorPairMap) \ 41 V(AllocationSiteWithWeakNextMap, allocation_site_map, AllocationSiteMap) \ 42 V(AllocationSiteWithoutWeakNextMap, allocation_site_without_weaknext_map, \ 43 AllocationSiteWithoutWeakNextMap) \ 44 V(BooleanMap, boolean_map, BooleanMap) \ 45 V(CodeMap, code_map, CodeMap) \ 46 V(EmptyFixedArray, empty_fixed_array, EmptyFixedArray) \ 47 V(EmptySlowElementDictionary, empty_slow_element_dictionary, \ 48 EmptySlowElementDictionary) \ 49 V(empty_string, empty_string, EmptyString) \ 50 V(FalseValue, false_value, False) \ 51 V(FeedbackVectorMap, feedback_vector_map, FeedbackVectorMap) \ 52 V(FixedArrayMap, fixed_array_map, FixedArrayMap) \ 53 V(FixedCOWArrayMap, fixed_cow_array_map, FixedCOWArrayMap) \ 54 V(FixedDoubleArrayMap, fixed_double_array_map, FixedDoubleArrayMap) \ 55 V(FunctionTemplateInfoMap, function_template_info_map, \ 56 FunctionTemplateInfoMap) \ 57 V(GlobalPropertyCellMap, global_property_cell_map, PropertyCellMap) \ 58 V(has_instance_symbol, has_instance_symbol, HasInstanceSymbol) \ 59 V(HeapNumberMap, heap_number_map, HeapNumberMap) \ 60 V(iterator_symbol, iterator_symbol, IteratorSymbol) \ 61 V(length_string, length_string, LengthString) \ 62 V(ManyClosuresCellMap, many_closures_cell_map, ManyClosuresCellMap) \ 63 V(MetaMap, meta_map, MetaMap) \ 64 V(MinusZeroValue, minus_zero_value, MinusZero) \ 65 V(MutableHeapNumberMap, mutable_heap_number_map, MutableHeapNumberMap) \ 66 V(NanValue, nan_value, Nan) \ 67 V(NoClosuresCellMap, no_closures_cell_map, NoClosuresCellMap) \ 68 V(NullValue, null_value, Null) \ 69 V(OneClosureCellMap, one_closure_cell_map, OneClosureCellMap) \ 70 V(PreParsedScopeDataMap, pre_parsed_scope_data_map, PreParsedScopeDataMap) \ 71 V(prototype_string, prototype_string, PrototypeString) \ 72 V(SharedFunctionInfoMap, shared_function_info_map, SharedFunctionInfoMap) \ 73 V(SymbolMap, symbol_map, SymbolMap) \ 74 V(TheHoleValue, the_hole_value, TheHole) \ 75 V(TransitionArrayMap, transition_array_map, TransitionArrayMap) \ 76 V(TrueValue, true_value, True) \ 77 V(Tuple2Map, tuple2_map, Tuple2Map) \ 78 V(Tuple3Map, tuple3_map, Tuple3Map) \ 79 V(ArrayBoilerplateDescriptionMap, array_boilerplate_description_map, \ 80 ArrayBoilerplateDescriptionMap) \ 81 V(UncompiledDataWithoutPreParsedScopeMap, \ 82 uncompiled_data_without_pre_parsed_scope_map, \ 83 UncompiledDataWithoutPreParsedScopeMap) \ 84 V(UncompiledDataWithPreParsedScopeMap, \ 85 uncompiled_data_with_pre_parsed_scope_map, \ 86 UncompiledDataWithPreParsedScopeMap) \ 87 V(UndefinedValue, undefined_value, Undefined) \ 88 V(WeakFixedArrayMap, weak_fixed_array_map, WeakFixedArrayMap) 89 90 #define HEAP_IMMOVABLE_OBJECT_LIST(V) \ 91 HEAP_MUTABLE_IMMOVABLE_OBJECT_LIST(V) \ 92 HEAP_IMMUTABLE_IMMOVABLE_OBJECT_LIST(V) 93 94 // Returned from IteratorBuiltinsAssembler::GetIterator(). Struct is declared 95 // here to simplify use in other generated builtins. 96 struct IteratorRecord { 97 public: 98 // iteratorRecord.[[Iterator]] 99 compiler::TNode<JSReceiver> object; 100 101 // iteratorRecord.[[NextMethod]] 102 compiler::TNode<Object> next; 103 }; 104 105 #ifdef DEBUG 106 #define CSA_CHECK(csa, x) \ 107 (csa)->Check( \ 108 [&]() -> compiler::Node* { \ 109 return implicit_cast<compiler::SloppyTNode<Word32T>>(x); \ 110 }, \ 111 #x, __FILE__, __LINE__) 112 #else 113 #define CSA_CHECK(csa, x) (csa)->FastCheck(x) 114 #endif 115 116 #ifdef DEBUG 117 // Add stringified versions to the given values, except the first. That is, 118 // transform 119 // x, a, b, c, d, e, f 120 // to 121 // a, "a", b, "b", c, "c", d, "d", e, "e", f, "f" 122 // 123 // __VA_ARGS__ is ignored to allow the caller to pass through too many 124 // parameters, and the first element is ignored to support having no extra 125 // values without empty __VA_ARGS__ (which cause all sorts of problems with 126 // extra commas). 127 #define CSA_ASSERT_STRINGIFY_EXTRA_VALUES_5(_, v1, v2, v3, v4, v5, ...) \ 128 v1, #v1, v2, #v2, v3, #v3, v4, #v4, v5, #v5 129 130 // Stringify the given variable number of arguments. The arguments are trimmed 131 // to 5 if there are too many, and padded with nullptr if there are not enough. 132 #define CSA_ASSERT_STRINGIFY_EXTRA_VALUES(...) \ 133 CSA_ASSERT_STRINGIFY_EXTRA_VALUES_5(__VA_ARGS__, nullptr, nullptr, nullptr, \ 134 nullptr, nullptr) 135 136 #define CSA_ASSERT_GET_FIRST(x, ...) (x) 137 #define CSA_ASSERT_GET_FIRST_STR(x, ...) #x 138 139 // CSA_ASSERT(csa, <condition>, <extra values to print...>) 140 141 // We have to jump through some hoops to allow <extra values to print...> to be 142 // empty. 143 #define CSA_ASSERT(csa, ...) \ 144 (csa)->Assert( \ 145 [&]() -> compiler::Node* { \ 146 return implicit_cast<compiler::SloppyTNode<Word32T>>( \ 147 EXPAND(CSA_ASSERT_GET_FIRST(__VA_ARGS__))); \ 148 }, \ 149 EXPAND(CSA_ASSERT_GET_FIRST_STR(__VA_ARGS__)), __FILE__, __LINE__, \ 150 CSA_ASSERT_STRINGIFY_EXTRA_VALUES(__VA_ARGS__)) 151 152 // CSA_ASSERT_BRANCH(csa, [](Label* ok, Label* not_ok) {...}, 153 // <extra values to print...>) 154 155 #define CSA_ASSERT_BRANCH(csa, ...) \ 156 (csa)->Assert(EXPAND(CSA_ASSERT_GET_FIRST(__VA_ARGS__)), \ 157 EXPAND(CSA_ASSERT_GET_FIRST_STR(__VA_ARGS__)), __FILE__, \ 158 __LINE__, CSA_ASSERT_STRINGIFY_EXTRA_VALUES(__VA_ARGS__)) 159 160 #define CSA_ASSERT_JS_ARGC_OP(csa, Op, op, expected) \ 161 (csa)->Assert( \ 162 [&]() -> compiler::Node* { \ 163 compiler::Node* const argc = \ 164 (csa)->Parameter(Descriptor::kJSActualArgumentsCount); \ 165 return (csa)->Op(argc, (csa)->Int32Constant(expected)); \ 166 }, \ 167 "argc " #op " " #expected, __FILE__, __LINE__, \ 168 SmiFromInt32((csa)->Parameter(Descriptor::kJSActualArgumentsCount)), \ 169 "argc") 170 171 #define CSA_ASSERT_JS_ARGC_EQ(csa, expected) \ 172 CSA_ASSERT_JS_ARGC_OP(csa, Word32Equal, ==, expected) 173 174 #define CSA_DEBUG_INFO(name) \ 175 { #name, __FILE__, __LINE__ } 176 #define BIND(label) Bind(label, CSA_DEBUG_INFO(label)) 177 #define VARIABLE(name, ...) \ 178 Variable name(this, CSA_DEBUG_INFO(name), __VA_ARGS__) 179 #define VARIABLE_CONSTRUCTOR(name, ...) \ 180 name(this, CSA_DEBUG_INFO(name), __VA_ARGS__) 181 #define TYPED_VARIABLE_DEF(type, name, ...) \ 182 TVariable<type> name(CSA_DEBUG_INFO(name), __VA_ARGS__) 183 #else // DEBUG 184 #define CSA_ASSERT(csa, ...) ((void)0) 185 #define CSA_ASSERT_BRANCH(csa, ...) ((void)0) 186 #define CSA_ASSERT_JS_ARGC_EQ(csa, expected) ((void)0) 187 #define BIND(label) Bind(label) 188 #define VARIABLE(name, ...) Variable name(this, __VA_ARGS__) 189 #define VARIABLE_CONSTRUCTOR(name, ...) name(this, __VA_ARGS__) 190 #define TYPED_VARIABLE_DEF(type, name, ...) TVariable<type> name(__VA_ARGS__) 191 #endif // DEBUG 192 193 #define TVARIABLE(...) EXPAND(TYPED_VARIABLE_DEF(__VA_ARGS__, this)) 194 195 #ifdef ENABLE_SLOW_DCHECKS 196 #define CSA_SLOW_ASSERT(csa, ...) \ 197 if (FLAG_enable_slow_asserts) { \ 198 CSA_ASSERT(csa, __VA_ARGS__); \ 199 } 200 #else 201 #define CSA_SLOW_ASSERT(csa, ...) ((void)0) 202 #endif 203 204 class int31_t { 205 public: int31_t()206 int31_t() : value_(0) {} int31_t(int value)207 int31_t(int value) : value_(value) { // NOLINT(runtime/explicit) 208 DCHECK_EQ((value & 0x80000000) != 0, (value & 0x40000000) != 0); 209 } 210 int31_t& operator=(int value) { 211 DCHECK_EQ((value & 0x80000000) != 0, (value & 0x40000000) != 0); 212 value_ = value; 213 return *this; 214 } value()215 int32_t value() const { return value_; } int32_t()216 operator int32_t() const { return value_; } 217 218 private: 219 int32_t value_; 220 }; 221 222 // Provides JavaScript-specific "macro-assembler" functionality on top of the 223 // CodeAssembler. By factoring the JavaScript-isms out of the CodeAssembler, 224 // it's possible to add JavaScript-specific useful CodeAssembler "macros" 225 // without modifying files in the compiler directory (and requiring a review 226 // from a compiler directory OWNER). 227 class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler { 228 public: 229 using Node = compiler::Node; 230 template <class T> 231 using TNode = compiler::TNode<T>; 232 template <class T> 233 using SloppyTNode = compiler::SloppyTNode<T>; 234 235 template <typename T> 236 using LazyNode = std::function<TNode<T>()>; 237 238 CodeStubAssembler(compiler::CodeAssemblerState* state); 239 240 enum AllocationFlag : uint8_t { 241 kNone = 0, 242 kDoubleAlignment = 1, 243 kPretenured = 1 << 1, 244 kAllowLargeObjectAllocation = 1 << 2, 245 }; 246 247 enum SlackTrackingMode { kWithSlackTracking, kNoSlackTracking }; 248 249 typedef base::Flags<AllocationFlag> AllocationFlags; 250 251 enum ParameterMode { SMI_PARAMETERS, INTPTR_PARAMETERS }; 252 253 // On 32-bit platforms, there is a slight performance advantage to doing all 254 // of the array offset/index arithmetic with SMIs, since it's possible 255 // to save a few tag/untag operations without paying an extra expense when 256 // calculating array offset (the smi math can be folded away) and there are 257 // fewer live ranges. Thus only convert indices to untagged value on 64-bit 258 // platforms. OptimalParameterMode()259 ParameterMode OptimalParameterMode() const { 260 return Is64() ? INTPTR_PARAMETERS : SMI_PARAMETERS; 261 } 262 ParameterRepresentation(ParameterMode mode)263 MachineRepresentation ParameterRepresentation(ParameterMode mode) const { 264 return mode == INTPTR_PARAMETERS ? MachineType::PointerRepresentation() 265 : MachineRepresentation::kTaggedSigned; 266 } 267 OptimalParameterRepresentation()268 MachineRepresentation OptimalParameterRepresentation() const { 269 return ParameterRepresentation(OptimalParameterMode()); 270 } 271 ParameterToIntPtr(Node * value,ParameterMode mode)272 TNode<IntPtrT> ParameterToIntPtr(Node* value, ParameterMode mode) { 273 if (mode == SMI_PARAMETERS) value = SmiUntag(value); 274 return UncheckedCast<IntPtrT>(value); 275 } 276 IntPtrToParameter(SloppyTNode<IntPtrT> value,ParameterMode mode)277 Node* IntPtrToParameter(SloppyTNode<IntPtrT> value, ParameterMode mode) { 278 if (mode == SMI_PARAMETERS) return SmiTag(value); 279 return value; 280 } 281 Int32ToParameter(SloppyTNode<Int32T> value,ParameterMode mode)282 Node* Int32ToParameter(SloppyTNode<Int32T> value, ParameterMode mode) { 283 return IntPtrToParameter(ChangeInt32ToIntPtr(value), mode); 284 } 285 ParameterToTagged(Node * value,ParameterMode mode)286 TNode<Smi> ParameterToTagged(Node* value, ParameterMode mode) { 287 if (mode != SMI_PARAMETERS) return SmiTag(value); 288 return UncheckedCast<Smi>(value); 289 } 290 TaggedToParameter(SloppyTNode<Smi> value,ParameterMode mode)291 Node* TaggedToParameter(SloppyTNode<Smi> value, ParameterMode mode) { 292 if (mode != SMI_PARAMETERS) return SmiUntag(value); 293 return value; 294 } 295 TaggedToSmi(TNode<Object> value,Label * fail)296 TNode<Smi> TaggedToSmi(TNode<Object> value, Label* fail) { 297 GotoIf(TaggedIsNotSmi(value), fail); 298 return UncheckedCast<Smi>(value); 299 } 300 TaggedToNumber(TNode<Object> value,Label * fail)301 TNode<Number> TaggedToNumber(TNode<Object> value, Label* fail) { 302 GotoIfNot(IsNumber(value), fail); 303 return UncheckedCast<Number>(value); 304 } 305 TaggedToHeapObject(TNode<Object> value,Label * fail)306 TNode<HeapObject> TaggedToHeapObject(TNode<Object> value, Label* fail) { 307 GotoIf(TaggedIsSmi(value), fail); 308 return UncheckedCast<HeapObject>(value); 309 } 310 HeapObjectToJSArray(TNode<HeapObject> heap_object,Label * fail)311 TNode<JSArray> HeapObjectToJSArray(TNode<HeapObject> heap_object, 312 Label* fail) { 313 GotoIfNot(IsJSArray(heap_object), fail); 314 return UncheckedCast<JSArray>(heap_object); 315 } 316 TaggedToFastJSArray(TNode<Context> context,TNode<Object> value,Label * fail)317 TNode<JSArray> TaggedToFastJSArray(TNode<Context> context, 318 TNode<Object> value, Label* fail) { 319 GotoIf(TaggedIsSmi(value), fail); 320 TNode<HeapObject> heap_object = CAST(value); 321 GotoIfNot(IsFastJSArray(heap_object, context), fail); 322 return UncheckedCast<JSArray>(heap_object); 323 } 324 HeapObjectToJSDataView(TNode<HeapObject> heap_object,Label * fail)325 TNode<JSDataView> HeapObjectToJSDataView(TNode<HeapObject> heap_object, 326 Label* fail) { 327 GotoIfNot(IsJSDataView(heap_object), fail); 328 return CAST(heap_object); 329 } 330 HeapObjectToCallable(TNode<HeapObject> heap_object,Label * fail)331 TNode<JSReceiver> HeapObjectToCallable(TNode<HeapObject> heap_object, 332 Label* fail) { 333 GotoIfNot(IsCallable(heap_object), fail); 334 return CAST(heap_object); 335 } 336 UnsafeCastNumberToHeapNumber(TNode<Number> p_n)337 TNode<HeapNumber> UnsafeCastNumberToHeapNumber(TNode<Number> p_n) { 338 return CAST(p_n); 339 } 340 UnsafeCastObjectToFixedArrayBase(TNode<Object> p_o)341 TNode<FixedArrayBase> UnsafeCastObjectToFixedArrayBase(TNode<Object> p_o) { 342 return CAST(p_o); 343 } 344 UnsafeCastObjectToFixedArray(TNode<Object> p_o)345 TNode<FixedArray> UnsafeCastObjectToFixedArray(TNode<Object> p_o) { 346 return CAST(p_o); 347 } 348 UnsafeCastObjectToFixedDoubleArray(TNode<Object> p_o)349 TNode<FixedDoubleArray> UnsafeCastObjectToFixedDoubleArray( 350 TNode<Object> p_o) { 351 return CAST(p_o); 352 } 353 UnsafeCastObjectToHeapNumber(TNode<Object> p_o)354 TNode<HeapNumber> UnsafeCastObjectToHeapNumber(TNode<Object> p_o) { 355 return CAST(p_o); 356 } 357 UnsafeCastObjectToCallable(TNode<Object> p_o)358 TNode<HeapObject> UnsafeCastObjectToCallable(TNode<Object> p_o) { 359 return CAST(p_o); 360 } 361 UnsafeCastObjectToSmi(TNode<Object> p_o)362 TNode<Smi> UnsafeCastObjectToSmi(TNode<Object> p_o) { return CAST(p_o); } 363 UnsafeCastObjectToNumber(TNode<Object> p_o)364 TNode<Number> UnsafeCastObjectToNumber(TNode<Object> p_o) { 365 return CAST(p_o); 366 } 367 UnsafeCastObjectToHeapObject(TNode<Object> p_o)368 TNode<HeapObject> UnsafeCastObjectToHeapObject(TNode<Object> p_o) { 369 return CAST(p_o); 370 } 371 UnsafeCastObjectToJSArray(TNode<Object> p_o)372 TNode<JSArray> UnsafeCastObjectToJSArray(TNode<Object> p_o) { 373 return CAST(p_o); 374 } 375 UnsafeCastObjectToFixedTypedArrayBase(TNode<Object> p_o)376 TNode<FixedTypedArrayBase> UnsafeCastObjectToFixedTypedArrayBase( 377 TNode<Object> p_o) { 378 return CAST(p_o); 379 } 380 UnsafeCastObjectToCompareBuiltinFn(TNode<Object> p_o)381 TNode<Object> UnsafeCastObjectToCompareBuiltinFn(TNode<Object> p_o) { 382 return p_o; 383 } 384 UnsafeCastObjectToLoadFn(TNode<Object> p_o)385 TNode<Object> UnsafeCastObjectToLoadFn(TNode<Object> p_o) { return p_o; } UnsafeCastObjectToStoreFn(TNode<Object> p_o)386 TNode<Object> UnsafeCastObjectToStoreFn(TNode<Object> p_o) { return p_o; } UnsafeCastObjectToCanUseSameAccessorFn(TNode<Object> p_o)387 TNode<Object> UnsafeCastObjectToCanUseSameAccessorFn(TNode<Object> p_o) { 388 return p_o; 389 } 390 UnsafeCastObjectToNumberDictionary(TNode<Object> p_o)391 TNode<NumberDictionary> UnsafeCastObjectToNumberDictionary( 392 TNode<Object> p_o) { 393 return CAST(p_o); 394 } 395 UnsafeCastObjectToJSReceiver(TNode<Object> p_o)396 TNode<JSReceiver> UnsafeCastObjectToJSReceiver(TNode<Object> p_o) { 397 return CAST(p_o); 398 } 399 UnsafeCastObjectToJSObject(TNode<Object> p_o)400 TNode<JSObject> UnsafeCastObjectToJSObject(TNode<Object> p_o) { 401 return CAST(p_o); 402 } 403 UnsafeCastObjectToMap(TNode<Object> p_o)404 TNode<Map> UnsafeCastObjectToMap(TNode<Object> p_o) { return CAST(p_o); } 405 406 Node* MatchesParameterMode(Node* value, ParameterMode mode); 407 408 #define PARAMETER_BINOP(OpName, IntPtrOpName, SmiOpName) \ 409 Node* OpName(Node* a, Node* b, ParameterMode mode) { \ 410 if (mode == SMI_PARAMETERS) { \ 411 return SmiOpName(CAST(a), CAST(b)); \ 412 } else { \ 413 DCHECK_EQ(INTPTR_PARAMETERS, mode); \ 414 return IntPtrOpName(a, b); \ 415 } \ 416 } 417 PARAMETER_BINOP(IntPtrOrSmiMin, IntPtrMin, SmiMin) 418 PARAMETER_BINOP(IntPtrOrSmiAdd, IntPtrAdd, SmiAdd) 419 PARAMETER_BINOP(IntPtrOrSmiSub, IntPtrSub, SmiSub) 420 PARAMETER_BINOP(IntPtrOrSmiLessThan, IntPtrLessThan, SmiLessThan) 421 PARAMETER_BINOP(IntPtrOrSmiLessThanOrEqual, IntPtrLessThanOrEqual, 422 SmiLessThanOrEqual) 423 PARAMETER_BINOP(IntPtrOrSmiGreaterThan, IntPtrGreaterThan, SmiGreaterThan) 424 PARAMETER_BINOP(IntPtrOrSmiGreaterThanOrEqual, IntPtrGreaterThanOrEqual, 425 SmiGreaterThanOrEqual) 426 PARAMETER_BINOP(UintPtrOrSmiLessThan, UintPtrLessThan, SmiBelow) 427 PARAMETER_BINOP(UintPtrOrSmiGreaterThanOrEqual, UintPtrGreaterThanOrEqual, 428 SmiAboveOrEqual) 429 #undef PARAMETER_BINOP 430 431 TNode<Object> NoContextConstant(); 432 433 #define HEAP_CONSTANT_ACCESSOR(rootIndexName, rootAccessorName, name) \ 434 compiler::TNode<std::remove_reference<decltype( \ 435 *std::declval<ReadOnlyRoots>().rootAccessorName())>::type> \ 436 name##Constant(); 437 HEAP_IMMUTABLE_IMMOVABLE_OBJECT_LIST(HEAP_CONSTANT_ACCESSOR) 438 #undef HEAP_CONSTANT_ACCESSOR 439 440 #define HEAP_CONSTANT_ACCESSOR(rootIndexName, rootAccessorName, name) \ 441 compiler::TNode<std::remove_reference<decltype( \ 442 *std::declval<Heap>().rootAccessorName())>::type> \ 443 name##Constant(); 444 HEAP_MUTABLE_IMMOVABLE_OBJECT_LIST(HEAP_CONSTANT_ACCESSOR) 445 #undef HEAP_CONSTANT_ACCESSOR 446 447 #define HEAP_CONSTANT_TEST(rootIndexName, rootAccessorName, name) \ 448 TNode<BoolT> Is##name(SloppyTNode<Object> value); \ 449 TNode<BoolT> IsNot##name(SloppyTNode<Object> value); 450 HEAP_IMMOVABLE_OBJECT_LIST(HEAP_CONSTANT_TEST) 451 #undef HEAP_CONSTANT_TEST 452 453 TNode<Int64T> HashSeed(); 454 TNode<Int32T> HashSeedHigh(); 455 TNode<Int32T> HashSeedLow(); 456 457 Node* IntPtrOrSmiConstant(int value, ParameterMode mode); LanguageModeConstant(LanguageMode mode)458 TNode<Smi> LanguageModeConstant(LanguageMode mode) { 459 return SmiConstant(static_cast<int>(mode)); 460 } 461 462 bool IsIntPtrOrSmiConstantZero(Node* test, ParameterMode mode); 463 bool TryGetIntPtrOrSmiConstantValue(Node* maybe_constant, int* value, 464 ParameterMode mode); 465 466 // Round the 32bits payload of the provided word up to the next power of two. 467 TNode<IntPtrT> IntPtrRoundUpToPowerOfTwo32(TNode<IntPtrT> value); 468 // Select the maximum of the two provided IntPtr values. 469 TNode<IntPtrT> IntPtrMax(SloppyTNode<IntPtrT> left, 470 SloppyTNode<IntPtrT> right); 471 // Select the minimum of the two provided IntPtr values. 472 TNode<IntPtrT> IntPtrMin(SloppyTNode<IntPtrT> left, 473 SloppyTNode<IntPtrT> right); 474 475 // Float64 operations. 476 TNode<Float64T> Float64Ceil(SloppyTNode<Float64T> x); 477 TNode<Float64T> Float64Floor(SloppyTNode<Float64T> x); 478 TNode<Float64T> Float64Round(SloppyTNode<Float64T> x); 479 TNode<Float64T> Float64RoundToEven(SloppyTNode<Float64T> x); 480 TNode<Float64T> Float64Trunc(SloppyTNode<Float64T> x); 481 // Select the minimum of the two provided Number values. 482 TNode<Object> NumberMax(SloppyTNode<Object> left, SloppyTNode<Object> right); 483 // Select the minimum of the two provided Number values. 484 TNode<Object> NumberMin(SloppyTNode<Object> left, SloppyTNode<Object> right); 485 486 // After converting an index to an integer, calculate a relative index: if 487 // index < 0, max(length + index, 0); else min(index, length) 488 TNode<IntPtrT> ConvertToRelativeIndex(TNode<Context> context, 489 TNode<Object> index, 490 TNode<IntPtrT> length); 491 492 // Returns true iff the given value fits into smi range and is >= 0. 493 TNode<BoolT> IsValidPositiveSmi(TNode<IntPtrT> value); 494 495 // Tag an IntPtr as a Smi value. 496 TNode<Smi> SmiTag(SloppyTNode<IntPtrT> value); 497 // Untag a Smi value as an IntPtr. 498 TNode<IntPtrT> SmiUntag(SloppyTNode<Smi> value); 499 500 // Smi conversions. 501 TNode<Float64T> SmiToFloat64(SloppyTNode<Smi> value); SmiFromIntPtr(SloppyTNode<IntPtrT> value)502 TNode<Smi> SmiFromIntPtr(SloppyTNode<IntPtrT> value) { return SmiTag(value); } 503 TNode<Smi> SmiFromInt32(SloppyTNode<Int32T> value); SmiToIntPtr(SloppyTNode<Smi> value)504 TNode<IntPtrT> SmiToIntPtr(SloppyTNode<Smi> value) { return SmiUntag(value); } 505 TNode<Int32T> SmiToInt32(SloppyTNode<Smi> value); 506 507 // Smi operations. 508 #define SMI_ARITHMETIC_BINOP(SmiOpName, IntPtrOpName, Int32OpName) \ 509 TNode<Smi> SmiOpName(TNode<Smi> a, TNode<Smi> b) { \ 510 if (SmiValuesAre32Bits()) { \ 511 return BitcastWordToTaggedSigned( \ 512 IntPtrOpName(BitcastTaggedToWord(a), BitcastTaggedToWord(b))); \ 513 } else { \ 514 DCHECK(SmiValuesAre31Bits()); \ 515 if (kPointerSize == kInt64Size) { \ 516 CSA_ASSERT(this, IsValidSmi(a)); \ 517 CSA_ASSERT(this, IsValidSmi(b)); \ 518 } \ 519 return BitcastWordToTaggedSigned(ChangeInt32ToIntPtr( \ 520 Int32OpName(TruncateIntPtrToInt32(BitcastTaggedToWord(a)), \ 521 TruncateIntPtrToInt32(BitcastTaggedToWord(b))))); \ 522 } \ 523 } SMI_ARITHMETIC_BINOP(SmiAdd,IntPtrAdd,Int32Add)524 SMI_ARITHMETIC_BINOP(SmiAdd, IntPtrAdd, Int32Add) 525 SMI_ARITHMETIC_BINOP(SmiSub, IntPtrSub, Int32Sub) 526 SMI_ARITHMETIC_BINOP(SmiAnd, WordAnd, Word32And) 527 SMI_ARITHMETIC_BINOP(SmiOr, WordOr, Word32Or) 528 #undef SMI_ARITHMETIC_BINOP 529 TNode<Smi> SmiInc(TNode<Smi> value) { return SmiAdd(value, SmiConstant(1)); } 530 531 TNode<Smi> TrySmiAdd(TNode<Smi> a, TNode<Smi> b, Label* if_overflow); 532 TNode<Smi> TrySmiSub(TNode<Smi> a, TNode<Smi> b, Label* if_overflow); 533 SmiShl(TNode<Smi> a,int shift)534 TNode<Smi> SmiShl(TNode<Smi> a, int shift) { 535 return BitcastWordToTaggedSigned(WordShl(BitcastTaggedToWord(a), shift)); 536 } 537 SmiShr(TNode<Smi> a,int shift)538 TNode<Smi> SmiShr(TNode<Smi> a, int shift) { 539 return BitcastWordToTaggedSigned( 540 WordAnd(WordShr(BitcastTaggedToWord(a), shift), 541 BitcastTaggedToWord(SmiConstant(-1)))); 542 } 543 WordOrSmiShl(Node * a,int shift,ParameterMode mode)544 Node* WordOrSmiShl(Node* a, int shift, ParameterMode mode) { 545 if (mode == SMI_PARAMETERS) { 546 return SmiShl(CAST(a), shift); 547 } else { 548 DCHECK_EQ(INTPTR_PARAMETERS, mode); 549 return WordShl(a, shift); 550 } 551 } 552 WordOrSmiShr(Node * a,int shift,ParameterMode mode)553 Node* WordOrSmiShr(Node* a, int shift, ParameterMode mode) { 554 if (mode == SMI_PARAMETERS) { 555 return SmiShr(CAST(a), shift); 556 } else { 557 DCHECK_EQ(INTPTR_PARAMETERS, mode); 558 return WordShr(a, shift); 559 } 560 } 561 562 #define SMI_COMPARISON_OP(SmiOpName, IntPtrOpName, Int32OpName) \ 563 TNode<BoolT> SmiOpName(TNode<Smi> a, TNode<Smi> b) { \ 564 if (SmiValuesAre32Bits()) { \ 565 return IntPtrOpName(BitcastTaggedToWord(a), BitcastTaggedToWord(b)); \ 566 } else { \ 567 DCHECK(SmiValuesAre31Bits()); \ 568 if (kPointerSize == kInt64Size) { \ 569 CSA_ASSERT(this, IsValidSmi(a)); \ 570 CSA_ASSERT(this, IsValidSmi(b)); \ 571 } \ 572 return Int32OpName(TruncateIntPtrToInt32(BitcastTaggedToWord(a)), \ 573 TruncateIntPtrToInt32(BitcastTaggedToWord(b))); \ 574 } \ 575 } 576 SMI_COMPARISON_OP(SmiEqual, WordEqual, Word32Equal) 577 SMI_COMPARISON_OP(SmiNotEqual, WordNotEqual, Word32NotEqual) 578 SMI_COMPARISON_OP(SmiAbove, UintPtrGreaterThan, Uint32GreaterThan) 579 SMI_COMPARISON_OP(SmiAboveOrEqual, UintPtrGreaterThanOrEqual, 580 Uint32GreaterThanOrEqual) 581 SMI_COMPARISON_OP(SmiBelow, UintPtrLessThan, Uint32LessThan) 582 SMI_COMPARISON_OP(SmiLessThan, IntPtrLessThan, Int32LessThan) 583 SMI_COMPARISON_OP(SmiLessThanOrEqual, IntPtrLessThanOrEqual, 584 Int32LessThanOrEqual) 585 SMI_COMPARISON_OP(SmiGreaterThan, IntPtrGreaterThan, Int32GreaterThan) 586 SMI_COMPARISON_OP(SmiGreaterThanOrEqual, IntPtrGreaterThanOrEqual, 587 Int32GreaterThanOrEqual) 588 #undef SMI_COMPARISON_OP 589 TNode<Smi> SmiMax(TNode<Smi> a, TNode<Smi> b); 590 TNode<Smi> SmiMin(TNode<Smi> a, TNode<Smi> b); 591 // Computes a % b for Smi inputs a and b; result is not necessarily a Smi. 592 TNode<Number> SmiMod(TNode<Smi> a, TNode<Smi> b); 593 // Computes a * b for Smi inputs a and b; result is not necessarily a Smi. 594 TNode<Number> SmiMul(TNode<Smi> a, TNode<Smi> b); 595 // Tries to compute dividend / divisor for Smi inputs; branching to bailout 596 // if the division needs to be performed as a floating point operation. 597 TNode<Smi> TrySmiDiv(TNode<Smi> dividend, TNode<Smi> divisor, Label* bailout); 598 599 // Smi | HeapNumber operations. 600 TNode<Number> NumberInc(SloppyTNode<Number> value); 601 TNode<Number> NumberDec(SloppyTNode<Number> value); 602 TNode<Number> NumberAdd(SloppyTNode<Number> a, SloppyTNode<Number> b); 603 TNode<Number> NumberSub(SloppyTNode<Number> a, SloppyTNode<Number> b); 604 void GotoIfNotNumber(Node* value, Label* is_not_number); 605 void GotoIfNumber(Node* value, Label* is_number); SmiToNumber(TNode<Smi> v)606 TNode<Number> SmiToNumber(TNode<Smi> v) { return v; } 607 608 TNode<Number> BitwiseOp(Node* left32, Node* right32, Operation bitwise_op); 609 610 // Allocate an object of the given size. 611 Node* AllocateInNewSpace(Node* size, AllocationFlags flags = kNone); 612 Node* AllocateInNewSpace(int size, AllocationFlags flags = kNone); 613 Node* Allocate(Node* size, AllocationFlags flags = kNone); 614 Node* Allocate(int size, AllocationFlags flags = kNone); 615 Node* InnerAllocate(Node* previous, int offset); 616 Node* InnerAllocate(Node* previous, Node* offset); 617 Node* IsRegularHeapObjectSize(Node* size); 618 619 typedef std::function<void(Label*, Label*)> BranchGenerator; 620 typedef std::function<Node*()> NodeGenerator; 621 622 void Assert(const BranchGenerator& branch, const char* message = nullptr, 623 const char* file = nullptr, int line = 0, 624 Node* extra_node1 = nullptr, const char* extra_node1_name = "", 625 Node* extra_node2 = nullptr, const char* extra_node2_name = "", 626 Node* extra_node3 = nullptr, const char* extra_node3_name = "", 627 Node* extra_node4 = nullptr, const char* extra_node4_name = "", 628 Node* extra_node5 = nullptr, const char* extra_node5_name = ""); 629 void Assert(const NodeGenerator& condition_body, 630 const char* message = nullptr, const char* file = nullptr, 631 int line = 0, Node* extra_node1 = nullptr, 632 const char* extra_node1_name = "", Node* extra_node2 = nullptr, 633 const char* extra_node2_name = "", Node* extra_node3 = nullptr, 634 const char* extra_node3_name = "", Node* extra_node4 = nullptr, 635 const char* extra_node4_name = "", Node* extra_node5 = nullptr, 636 const char* extra_node5_name = ""); 637 void Check(const BranchGenerator& branch, const char* message = nullptr, 638 const char* file = nullptr, int line = 0, 639 Node* extra_node1 = nullptr, const char* extra_node1_name = "", 640 Node* extra_node2 = nullptr, const char* extra_node2_name = "", 641 Node* extra_node3 = nullptr, const char* extra_node3_name = "", 642 Node* extra_node4 = nullptr, const char* extra_node4_name = "", 643 Node* extra_node5 = nullptr, const char* extra_node5_name = ""); 644 void Check(const NodeGenerator& condition_body, const char* message = nullptr, 645 const char* file = nullptr, int line = 0, 646 Node* extra_node1 = nullptr, const char* extra_node1_name = "", 647 Node* extra_node2 = nullptr, const char* extra_node2_name = "", 648 Node* extra_node3 = nullptr, const char* extra_node3_name = "", 649 Node* extra_node4 = nullptr, const char* extra_node4_name = "", 650 Node* extra_node5 = nullptr, const char* extra_node5_name = ""); 651 void FastCheck(TNode<BoolT> condition); 652 653 // The following Call wrappers call an object according to the semantics that 654 // one finds in the EcmaScript spec, operating on an Callable (e.g. a 655 // JSFunction or proxy) rather than a Code object. 656 template <class... TArgs> Call(TNode<Context> context,TNode<Object> callable,TNode<JSReceiver> receiver,TArgs...args)657 TNode<Object> Call(TNode<Context> context, TNode<Object> callable, 658 TNode<JSReceiver> receiver, TArgs... args) { 659 return UncheckedCast<Object>(CallJS( 660 CodeFactory::Call(isolate(), ConvertReceiverMode::kNotNullOrUndefined), 661 context, callable, receiver, args...)); 662 } 663 template <class... TArgs> Call(TNode<Context> context,TNode<Object> callable,TNode<Object> receiver,TArgs...args)664 TNode<Object> Call(TNode<Context> context, TNode<Object> callable, 665 TNode<Object> receiver, TArgs... args) { 666 if (IsUndefinedConstant(receiver) || IsNullConstant(receiver)) { 667 return UncheckedCast<Object>(CallJS( 668 CodeFactory::Call(isolate(), ConvertReceiverMode::kNullOrUndefined), 669 context, callable, receiver, args...)); 670 } 671 return UncheckedCast<Object>(CallJS(CodeFactory::Call(isolate()), context, 672 callable, receiver, args...)); 673 } 674 675 template <class A, class F, class G> Select(SloppyTNode<BoolT> condition,const F & true_body,const G & false_body)676 TNode<A> Select(SloppyTNode<BoolT> condition, const F& true_body, 677 const G& false_body) { 678 return UncheckedCast<A>(SelectImpl( 679 condition, 680 [&]() -> Node* { return implicit_cast<TNode<A>>(true_body()); }, 681 [&]() -> Node* { return implicit_cast<TNode<A>>(false_body()); }, 682 MachineRepresentationOf<A>::value)); 683 } 684 685 template <class A> SelectConstant(TNode<BoolT> condition,TNode<A> true_value,TNode<A> false_value)686 TNode<A> SelectConstant(TNode<BoolT> condition, TNode<A> true_value, 687 TNode<A> false_value) { 688 return Select<A>(condition, [=] { return true_value; }, 689 [=] { return false_value; }); 690 } 691 692 TNode<Int32T> SelectInt32Constant(SloppyTNode<BoolT> condition, 693 int true_value, int false_value); 694 TNode<IntPtrT> SelectIntPtrConstant(SloppyTNode<BoolT> condition, 695 int true_value, int false_value); 696 TNode<Oddball> SelectBooleanConstant(SloppyTNode<BoolT> condition); 697 TNode<Smi> SelectSmiConstant(SloppyTNode<BoolT> condition, Smi* true_value, 698 Smi* false_value); SelectSmiConstant(SloppyTNode<BoolT> condition,int true_value,Smi * false_value)699 TNode<Smi> SelectSmiConstant(SloppyTNode<BoolT> condition, int true_value, 700 Smi* false_value) { 701 return SelectSmiConstant(condition, Smi::FromInt(true_value), false_value); 702 } SelectSmiConstant(SloppyTNode<BoolT> condition,Smi * true_value,int false_value)703 TNode<Smi> SelectSmiConstant(SloppyTNode<BoolT> condition, Smi* true_value, 704 int false_value) { 705 return SelectSmiConstant(condition, true_value, Smi::FromInt(false_value)); 706 } SelectSmiConstant(SloppyTNode<BoolT> condition,int true_value,int false_value)707 TNode<Smi> SelectSmiConstant(SloppyTNode<BoolT> condition, int true_value, 708 int false_value) { 709 return SelectSmiConstant(condition, Smi::FromInt(true_value), 710 Smi::FromInt(false_value)); 711 } 712 713 TNode<Int32T> TruncateIntPtrToInt32(SloppyTNode<IntPtrT> value); 714 715 // Check a value for smi-ness 716 TNode<BoolT> TaggedIsSmi(SloppyTNode<Object> a); 717 TNode<BoolT> TaggedIsSmi(TNode<MaybeObject> a); 718 TNode<BoolT> TaggedIsNotSmi(SloppyTNode<Object> a); 719 // Check that the value is a non-negative smi. 720 TNode<BoolT> TaggedIsPositiveSmi(SloppyTNode<Object> a); 721 // Check that a word has a word-aligned address. 722 TNode<BoolT> WordIsWordAligned(SloppyTNode<WordT> word); 723 TNode<BoolT> WordIsPowerOfTwo(SloppyTNode<IntPtrT> value); 724 725 #if DEBUG 726 void Bind(Label* label, AssemblerDebugInfo debug_info); 727 #else 728 void Bind(Label* label); 729 #endif // DEBUG 730 BranchIfSmiEqual(TNode<Smi> a,TNode<Smi> b,Label * if_true,Label * if_false)731 void BranchIfSmiEqual(TNode<Smi> a, TNode<Smi> b, Label* if_true, 732 Label* if_false) { 733 Branch(SmiEqual(a, b), if_true, if_false); 734 } 735 BranchIfSmiLessThan(TNode<Smi> a,TNode<Smi> b,Label * if_true,Label * if_false)736 void BranchIfSmiLessThan(TNode<Smi> a, TNode<Smi> b, Label* if_true, 737 Label* if_false) { 738 Branch(SmiLessThan(a, b), if_true, if_false); 739 } 740 BranchIfSmiLessThanOrEqual(TNode<Smi> a,TNode<Smi> b,Label * if_true,Label * if_false)741 void BranchIfSmiLessThanOrEqual(TNode<Smi> a, TNode<Smi> b, Label* if_true, 742 Label* if_false) { 743 Branch(SmiLessThanOrEqual(a, b), if_true, if_false); 744 } 745 BranchIfFloat64IsNaN(Node * value,Label * if_true,Label * if_false)746 void BranchIfFloat64IsNaN(Node* value, Label* if_true, Label* if_false) { 747 Branch(Float64Equal(value, value), if_false, if_true); 748 } 749 750 // Branches to {if_true} if ToBoolean applied to {value} yields true, 751 // otherwise goes to {if_false}. 752 void BranchIfToBooleanIsTrue(Node* value, Label* if_true, Label* if_false); 753 754 void BranchIfJSReceiver(Node* object, Label* if_true, Label* if_false); 755 756 void BranchIfFastJSArray(Node* object, Node* context, Label* if_true, 757 Label* if_false, bool iteration_only = false); BranchIfNotFastJSArray(Node * object,Node * context,Label * if_true,Label * if_false)758 void BranchIfNotFastJSArray(Node* object, Node* context, Label* if_true, 759 Label* if_false) { 760 BranchIfFastJSArray(object, context, if_false, if_true); 761 } 762 void BranchIfFastJSArrayForCopy(Node* object, Node* context, Label* if_true, 763 Label* if_false); 764 765 // Branches to {if_true} when --force-slow-path flag has been passed. 766 // It's used for testing to ensure that slow path implementation behave 767 // equivalent to corresponding fast paths (where applicable). 768 // 769 // Works only with V8_ENABLE_FORCE_SLOW_PATH compile time flag. Nop otherwise. 770 void GotoIfForceSlowPath(Label* if_true); 771 772 // Load value from current frame by given offset in bytes. 773 Node* LoadFromFrame(int offset, MachineType rep = MachineType::AnyTagged()); 774 // Load value from current parent frame by given offset in bytes. 775 Node* LoadFromParentFrame(int offset, 776 MachineType rep = MachineType::AnyTagged()); 777 778 // Load target function from the current JS frame. 779 // This is an alternative way of getting the target function in addition to 780 // Parameter(Descriptor::kJSTarget). The latter should be used near the 781 // beginning of builtin code while the target value is still in the register 782 // and the former should be used in slow paths in order to reduce register 783 // pressure on the fast path. 784 TNode<JSFunction> LoadTargetFromFrame(); 785 786 // Load an object pointer from a buffer that isn't in the heap. 787 Node* LoadBufferObject(Node* buffer, int offset, 788 MachineType rep = MachineType::AnyTagged()); 789 // Load a field from an object on the heap. 790 Node* LoadObjectField(SloppyTNode<HeapObject> object, int offset, 791 MachineType rep); 792 template <class T, typename std::enable_if< 793 std::is_convertible<TNode<T>, TNode<Object>>::value, 794 int>::type = 0> LoadObjectField(TNode<HeapObject> object,int offset)795 TNode<T> LoadObjectField(TNode<HeapObject> object, int offset) { 796 return CAST(LoadObjectField(object, offset, MachineTypeOf<T>::value)); 797 } 798 template <class T, typename std::enable_if< 799 std::is_convertible<TNode<T>, TNode<UntaggedT>>::value, 800 int>::type = 0> LoadObjectField(TNode<HeapObject> object,int offset)801 TNode<T> LoadObjectField(TNode<HeapObject> object, int offset) { 802 return UncheckedCast<T>( 803 LoadObjectField(object, offset, MachineTypeOf<T>::value)); 804 } LoadObjectField(SloppyTNode<HeapObject> object,int offset)805 TNode<Object> LoadObjectField(SloppyTNode<HeapObject> object, int offset) { 806 return UncheckedCast<Object>( 807 LoadObjectField(object, offset, MachineType::AnyTagged())); 808 } 809 Node* LoadObjectField(SloppyTNode<HeapObject> object, 810 SloppyTNode<IntPtrT> offset, MachineType rep); LoadObjectField(SloppyTNode<HeapObject> object,SloppyTNode<IntPtrT> offset)811 TNode<Object> LoadObjectField(SloppyTNode<HeapObject> object, 812 SloppyTNode<IntPtrT> offset) { 813 return UncheckedCast<Object>( 814 LoadObjectField(object, offset, MachineType::AnyTagged())); 815 } 816 // Load a SMI field and untag it. 817 TNode<IntPtrT> LoadAndUntagObjectField(SloppyTNode<HeapObject> object, 818 int offset); 819 // Load a SMI field, untag it, and convert to Word32. 820 TNode<Int32T> LoadAndUntagToWord32ObjectField(Node* object, int offset); 821 // Load a SMI and untag it. 822 TNode<IntPtrT> LoadAndUntagSmi(Node* base, int index); 823 // Load a SMI root, untag it, and convert to Word32. 824 TNode<Int32T> LoadAndUntagToWord32Root(Heap::RootListIndex root_index); 825 LoadMaybeWeakObjectField(SloppyTNode<HeapObject> object,int offset)826 TNode<MaybeObject> LoadMaybeWeakObjectField(SloppyTNode<HeapObject> object, 827 int offset) { 828 return UncheckedCast<MaybeObject>( 829 LoadObjectField(object, offset, MachineType::AnyTagged())); 830 } 831 832 // Tag a smi and store it. 833 Node* StoreAndTagSmi(Node* base, int offset, Node* value); 834 835 // Load the floating point value of a HeapNumber. 836 TNode<Float64T> LoadHeapNumberValue(SloppyTNode<HeapNumber> object); 837 // Load the Map of an HeapObject. 838 TNode<Map> LoadMap(SloppyTNode<HeapObject> object); 839 // Load the instance type of an HeapObject. 840 TNode<Int32T> LoadInstanceType(SloppyTNode<HeapObject> object); 841 // Compare the instance the type of the object against the provided one. 842 TNode<BoolT> HasInstanceType(SloppyTNode<HeapObject> object, 843 InstanceType type); 844 TNode<BoolT> DoesntHaveInstanceType(SloppyTNode<HeapObject> object, 845 InstanceType type); 846 TNode<BoolT> TaggedDoesntHaveInstanceType(SloppyTNode<HeapObject> any_tagged, 847 InstanceType type); 848 // Load the properties backing store of a JSObject. 849 TNode<HeapObject> LoadSlowProperties(SloppyTNode<JSObject> object); 850 TNode<HeapObject> LoadFastProperties(SloppyTNode<JSObject> object); 851 // Load the elements backing store of a JSObject. 852 TNode<FixedArrayBase> LoadElements(SloppyTNode<JSObject> object); 853 // Load the length of a JSArray instance. 854 TNode<Number> LoadJSArrayLength(SloppyTNode<JSArray> array); 855 // Load the length of a fast JSArray instance. Returns a positive Smi. 856 TNode<Smi> LoadFastJSArrayLength(SloppyTNode<JSArray> array); 857 // Load the length of a fixed array base instance. 858 TNode<Smi> LoadFixedArrayBaseLength(SloppyTNode<FixedArrayBase> array); 859 // Load the length of a fixed array base instance. 860 TNode<IntPtrT> LoadAndUntagFixedArrayBaseLength( 861 SloppyTNode<FixedArrayBase> array); 862 // Load the length of a WeakFixedArray. 863 TNode<Smi> LoadWeakFixedArrayLength(TNode<WeakFixedArray> array); 864 TNode<IntPtrT> LoadAndUntagWeakFixedArrayLength( 865 SloppyTNode<WeakFixedArray> array); 866 // Load the length of a JSTypedArray instance. 867 TNode<Smi> LoadTypedArrayLength(TNode<JSTypedArray> typed_array); 868 // Load the bit field of a Map. 869 TNode<Int32T> LoadMapBitField(SloppyTNode<Map> map); 870 // Load bit field 2 of a map. 871 TNode<Int32T> LoadMapBitField2(SloppyTNode<Map> map); 872 // Load bit field 3 of a map. 873 TNode<Uint32T> LoadMapBitField3(SloppyTNode<Map> map); 874 // Load the instance type of a map. 875 TNode<Int32T> LoadMapInstanceType(SloppyTNode<Map> map); 876 // Load the ElementsKind of a map. 877 TNode<Int32T> LoadMapElementsKind(SloppyTNode<Map> map); 878 TNode<Int32T> LoadElementsKind(SloppyTNode<HeapObject> map); 879 // Load the instance descriptors of a map. 880 TNode<DescriptorArray> LoadMapDescriptors(SloppyTNode<Map> map); 881 // Load the prototype of a map. 882 TNode<HeapObject> LoadMapPrototype(SloppyTNode<Map> map); 883 // Load the prototype info of a map. The result has to be checked if it is a 884 // prototype info object or not. 885 TNode<PrototypeInfo> LoadMapPrototypeInfo(SloppyTNode<Map> map, 886 Label* if_has_no_proto_info); 887 // Load the instance size of a Map. 888 TNode<IntPtrT> LoadMapInstanceSizeInWords(SloppyTNode<Map> map); 889 // Load the inobject properties start of a Map (valid only for JSObjects). 890 TNode<IntPtrT> LoadMapInobjectPropertiesStartInWords(SloppyTNode<Map> map); 891 // Load the constructor function index of a Map (only for primitive maps). 892 TNode<IntPtrT> LoadMapConstructorFunctionIndex(SloppyTNode<Map> map); 893 // Load the constructor of a Map (equivalent to Map::GetConstructor()). 894 TNode<Object> LoadMapConstructor(SloppyTNode<Map> map); 895 // Load the EnumLength of a Map. 896 Node* LoadMapEnumLength(SloppyTNode<Map> map); 897 // Load the back-pointer of a Map. 898 TNode<Object> LoadMapBackPointer(SloppyTNode<Map> map); 899 // Load the identity hash of a JSRececiver. 900 TNode<IntPtrT> LoadJSReceiverIdentityHash(SloppyTNode<Object> receiver, 901 Label* if_no_hash = nullptr); 902 903 // This is only used on a newly allocated PropertyArray which 904 // doesn't have an existing hash. 905 void InitializePropertyArrayLength(Node* property_array, Node* length, 906 ParameterMode mode); 907 908 // Check if the map is set for slow properties. 909 TNode<BoolT> IsDictionaryMap(SloppyTNode<Map> map); 910 911 // Load the hash field of a name as an uint32 value. 912 TNode<Uint32T> LoadNameHashField(SloppyTNode<Name> name); 913 // Load the hash value of a name as an uint32 value. 914 // If {if_hash_not_computed} label is specified then it also checks if 915 // hash is actually computed. 916 TNode<Uint32T> LoadNameHash(SloppyTNode<Name> name, 917 Label* if_hash_not_computed = nullptr); 918 919 // Load length field of a String object as intptr_t value. 920 TNode<IntPtrT> LoadStringLengthAsWord(SloppyTNode<String> object); 921 // Load length field of a String object as Smi value. 922 TNode<Smi> LoadStringLengthAsSmi(SloppyTNode<String> object); 923 // Loads a pointer to the sequential String char array. 924 Node* PointerToSeqStringData(Node* seq_string); 925 // Load value field of a JSValue object. 926 Node* LoadJSValueValue(Node* object); 927 928 // Figures out whether the value of maybe_object is: 929 // - a SMI (jump to "if_smi", "extracted" will be the SMI value) 930 // - a cleared weak reference (jump to "if_cleared", "extracted" will be 931 // untouched) 932 // - a weak reference (jump to "if_weak", "extracted" will be the object 933 // pointed to) 934 // - a strong reference (jump to "if_strong", "extracted" will be the object 935 // pointed to) 936 void DispatchMaybeObject(TNode<MaybeObject> maybe_object, Label* if_smi, 937 Label* if_cleared, Label* if_weak, Label* if_strong, 938 TVariable<Object>* extracted); 939 // See MaybeObject for semantics of these functions. 940 TNode<BoolT> IsStrongHeapObject(TNode<MaybeObject> value); 941 // This variant is for overzealous checking. IsStrongHeapObject(TNode<Object> value)942 TNode<BoolT> IsStrongHeapObject(TNode<Object> value) { 943 return IsStrongHeapObject(ReinterpretCast<MaybeObject>(value)); 944 } 945 TNode<HeapObject> ToStrongHeapObject(TNode<MaybeObject> value, 946 Label* if_not_strong); 947 948 TNode<BoolT> IsWeakOrClearedHeapObject(TNode<MaybeObject> value); 949 TNode<BoolT> IsClearedWeakHeapObject(TNode<MaybeObject> value); 950 TNode<BoolT> IsNotClearedWeakHeapObject(TNode<MaybeObject> value); 951 952 // Removes the weak bit + asserts it was set. 953 TNode<HeapObject> ToWeakHeapObject(TNode<MaybeObject> value); 954 955 TNode<HeapObject> ToWeakHeapObject(TNode<MaybeObject> value, 956 Label* if_cleared); 957 958 TNode<BoolT> IsWeakReferenceTo(TNode<MaybeObject> object, 959 TNode<Object> value); 960 TNode<BoolT> IsNotWeakReferenceTo(TNode<MaybeObject> object, 961 TNode<Object> value); 962 TNode<BoolT> IsStrongReferenceTo(TNode<MaybeObject> object, 963 TNode<Object> value); 964 965 TNode<MaybeObject> MakeWeak(TNode<HeapObject> value); 966 967 void FixedArrayBoundsCheck(TNode<FixedArrayBase> array, Node* index, 968 int additional_offset = 0, 969 ParameterMode parameter_mode = INTPTR_PARAMETERS); 970 971 // Load an array element from a FixedArray / WeakFixedArray / PropertyArray. 972 TNode<MaybeObject> LoadArrayElement( 973 SloppyTNode<HeapObject> object, int array_header_size, Node* index, 974 int additional_offset = 0, 975 ParameterMode parameter_mode = INTPTR_PARAMETERS, 976 LoadSensitivity needs_poisoning = LoadSensitivity::kSafe); 977 978 // Load an array element from a FixedArray. 979 TNode<Object> LoadFixedArrayElement( 980 TNode<FixedArray> object, Node* index, int additional_offset = 0, 981 ParameterMode parameter_mode = INTPTR_PARAMETERS, 982 LoadSensitivity needs_poisoning = LoadSensitivity::kSafe); 983 LoadFixedArrayElement(TNode<FixedArray> object,TNode<IntPtrT> index,LoadSensitivity needs_poisoning)984 TNode<Object> LoadFixedArrayElement(TNode<FixedArray> object, 985 TNode<IntPtrT> index, 986 LoadSensitivity needs_poisoning) { 987 return LoadFixedArrayElement(object, index, 0, INTPTR_PARAMETERS, 988 needs_poisoning); 989 } 990 991 TNode<Object> LoadFixedArrayElement( 992 TNode<FixedArray> object, TNode<IntPtrT> index, int additional_offset = 0, 993 LoadSensitivity needs_poisoning = LoadSensitivity::kSafe) { 994 return LoadFixedArrayElement(object, index, additional_offset, 995 INTPTR_PARAMETERS, needs_poisoning); 996 } 997 998 TNode<Object> LoadFixedArrayElement( 999 TNode<FixedArray> object, int index, int additional_offset = 0, 1000 LoadSensitivity needs_poisoning = LoadSensitivity::kSafe) { 1001 return LoadFixedArrayElement(object, IntPtrConstant(index), 1002 additional_offset, INTPTR_PARAMETERS, 1003 needs_poisoning); 1004 } LoadFixedArrayElement(TNode<FixedArray> object,TNode<Smi> index)1005 TNode<Object> LoadFixedArrayElement(TNode<FixedArray> object, 1006 TNode<Smi> index) { 1007 return LoadFixedArrayElement(object, index, 0, SMI_PARAMETERS); 1008 } 1009 1010 TNode<Object> LoadPropertyArrayElement(SloppyTNode<PropertyArray> object, 1011 SloppyTNode<IntPtrT> index); 1012 TNode<IntPtrT> LoadPropertyArrayLength(TNode<PropertyArray> object); 1013 1014 // Load an array element from a FixedArray / WeakFixedArray, untag it and 1015 // return it as Word32. 1016 TNode<Int32T> LoadAndUntagToWord32ArrayElement( 1017 SloppyTNode<HeapObject> object, int array_header_size, Node* index, 1018 int additional_offset = 0, 1019 ParameterMode parameter_mode = INTPTR_PARAMETERS); 1020 1021 // Load an array element from a FixedArray, untag it and return it as Word32. 1022 TNode<Int32T> LoadAndUntagToWord32FixedArrayElement( 1023 SloppyTNode<HeapObject> object, Node* index, int additional_offset = 0, 1024 ParameterMode parameter_mode = INTPTR_PARAMETERS); 1025 1026 TNode<Int32T> LoadAndUntagToWord32FixedArrayElement( 1027 SloppyTNode<HeapObject> object, int index, int additional_offset = 0) { 1028 return LoadAndUntagToWord32FixedArrayElement( 1029 object, IntPtrConstant(index), additional_offset, INTPTR_PARAMETERS); 1030 } 1031 1032 // Load an array element from a WeakFixedArray. 1033 TNode<MaybeObject> LoadWeakFixedArrayElement( 1034 TNode<WeakFixedArray> object, Node* index, int additional_offset = 0, 1035 ParameterMode parameter_mode = INTPTR_PARAMETERS, 1036 LoadSensitivity needs_poisoning = LoadSensitivity::kSafe); 1037 1038 TNode<MaybeObject> LoadWeakFixedArrayElement( 1039 TNode<WeakFixedArray> object, int index, int additional_offset = 0, 1040 LoadSensitivity needs_poisoning = LoadSensitivity::kSafe) { 1041 return LoadWeakFixedArrayElement(object, IntPtrConstant(index), 1042 additional_offset, INTPTR_PARAMETERS, 1043 needs_poisoning); 1044 } 1045 1046 // Load an array element from a FixedDoubleArray. 1047 TNode<Float64T> LoadFixedDoubleArrayElement( 1048 SloppyTNode<FixedDoubleArray> object, Node* index, 1049 MachineType machine_type, int additional_offset = 0, 1050 ParameterMode parameter_mode = INTPTR_PARAMETERS, 1051 Label* if_hole = nullptr); 1052 LoadFixedDoubleArrayElement(TNode<FixedDoubleArray> object,TNode<Smi> index)1053 Node* LoadFixedDoubleArrayElement(TNode<FixedDoubleArray> object, 1054 TNode<Smi> index) { 1055 return LoadFixedDoubleArrayElement(object, index, MachineType::Float64(), 0, 1056 SMI_PARAMETERS); 1057 } 1058 1059 // Load an array element from a FixedArray, FixedDoubleArray or a 1060 // NumberDictionary (depending on the |elements_kind|) and return 1061 // it as a tagged value. Assumes that the |index| passed a length 1062 // check before. Bails out to |if_accessor| if the element that 1063 // was found is an accessor, or to |if_hole| if the element at 1064 // the given |index| is not found in |elements|. 1065 TNode<Object> LoadFixedArrayBaseElementAsTagged( 1066 TNode<FixedArrayBase> elements, TNode<IntPtrT> index, 1067 TNode<Int32T> elements_kind, Label* if_accessor, Label* if_hole); 1068 1069 // Load a feedback slot from a FeedbackVector. 1070 TNode<MaybeObject> LoadFeedbackVectorSlot( 1071 Node* object, Node* index, int additional_offset = 0, 1072 ParameterMode parameter_mode = INTPTR_PARAMETERS); 1073 1074 TNode<IntPtrT> LoadFeedbackVectorLength(TNode<FeedbackVector>); 1075 TNode<Float64T> LoadDoubleWithHoleCheck(TNode<FixedDoubleArray> array, 1076 TNode<Smi> index, 1077 Label* if_hole = nullptr); 1078 1079 // Load Float64 value by |base| + |offset| address. If the value is a double 1080 // hole then jump to |if_hole|. If |machine_type| is None then only the hole 1081 // check is generated. 1082 TNode<Float64T> LoadDoubleWithHoleCheck( 1083 SloppyTNode<Object> base, SloppyTNode<IntPtrT> offset, Label* if_hole, 1084 MachineType machine_type = MachineType::Float64()); 1085 TNode<RawPtrT> LoadFixedTypedArrayBackingStore( 1086 TNode<FixedTypedArrayBase> typed_array); 1087 Node* LoadFixedTypedArrayElementAsTagged( 1088 Node* data_pointer, Node* index_node, ElementsKind elements_kind, 1089 ParameterMode parameter_mode = INTPTR_PARAMETERS); 1090 TNode<Numeric> LoadFixedTypedArrayElementAsTagged( 1091 TNode<WordT> data_pointer, TNode<Smi> index, TNode<Int32T> elements_kind); 1092 // Parts of the above, factored out for readability: 1093 Node* LoadFixedBigInt64ArrayElementAsTagged(Node* data_pointer, Node* offset); 1094 Node* LoadFixedBigUint64ArrayElementAsTagged(Node* data_pointer, 1095 Node* offset); 1096 1097 void StoreFixedTypedArrayElementFromTagged( 1098 TNode<Context> context, TNode<FixedTypedArrayBase> elements, 1099 TNode<Object> index_node, TNode<Object> value, ElementsKind elements_kind, 1100 ParameterMode parameter_mode); 1101 1102 // Context manipulation 1103 TNode<Object> LoadContextElement(SloppyTNode<Context> context, 1104 int slot_index); 1105 TNode<Object> LoadContextElement(SloppyTNode<Context> context, 1106 SloppyTNode<IntPtrT> slot_index); 1107 void StoreContextElement(SloppyTNode<Context> context, int slot_index, 1108 SloppyTNode<Object> value); 1109 void StoreContextElement(SloppyTNode<Context> context, 1110 SloppyTNode<IntPtrT> slot_index, 1111 SloppyTNode<Object> value); 1112 void StoreContextElementNoWriteBarrier(SloppyTNode<Context> context, 1113 int slot_index, 1114 SloppyTNode<Object> value); 1115 TNode<Context> LoadNativeContext(SloppyTNode<Context> context); 1116 // Calling this is only valid if there's a module context in the chain. 1117 TNode<Context> LoadModuleContext(SloppyTNode<Context> context); 1118 GotoIfContextElementEqual(Node * value,Node * native_context,int slot_index,Label * if_equal)1119 void GotoIfContextElementEqual(Node* value, Node* native_context, 1120 int slot_index, Label* if_equal) { 1121 GotoIf(WordEqual(value, LoadContextElement(native_context, slot_index)), 1122 if_equal); 1123 } 1124 1125 TNode<Map> LoadJSArrayElementsMap(ElementsKind kind, 1126 SloppyTNode<Context> native_context); 1127 TNode<Map> LoadJSArrayElementsMap(SloppyTNode<Int32T> kind, 1128 SloppyTNode<Context> native_context); 1129 1130 TNode<BoolT> IsGeneratorFunction(TNode<JSFunction> function); 1131 TNode<BoolT> HasPrototypeProperty(TNode<JSFunction> function, TNode<Map> map); 1132 void GotoIfPrototypeRequiresRuntimeLookup(TNode<JSFunction> function, 1133 TNode<Map> map, Label* runtime); 1134 // Load the "prototype" property of a JSFunction. 1135 Node* LoadJSFunctionPrototype(Node* function, Label* if_bailout); 1136 1137 Node* LoadSharedFunctionInfoBytecodeArray(Node* shared); 1138 1139 void StoreObjectByteNoWriteBarrier(TNode<HeapObject> object, int offset, 1140 TNode<Word32T> value); 1141 1142 // Store the floating point value of a HeapNumber. 1143 void StoreHeapNumberValue(SloppyTNode<HeapNumber> object, 1144 SloppyTNode<Float64T> value); 1145 void StoreMutableHeapNumberValue(SloppyTNode<MutableHeapNumber> object, 1146 SloppyTNode<Float64T> value); 1147 // Store a field to an object on the heap. 1148 Node* StoreObjectField(Node* object, int offset, Node* value); 1149 Node* StoreObjectField(Node* object, Node* offset, Node* value); 1150 Node* StoreObjectFieldNoWriteBarrier( 1151 Node* object, int offset, Node* value, 1152 MachineRepresentation rep = MachineRepresentation::kTagged); 1153 Node* StoreObjectFieldNoWriteBarrier( 1154 Node* object, Node* offset, Node* value, 1155 MachineRepresentation rep = MachineRepresentation::kTagged); 1156 // Store the Map of an HeapObject. 1157 Node* StoreMap(Node* object, Node* map); 1158 Node* StoreMapNoWriteBarrier(Node* object, 1159 Heap::RootListIndex map_root_index); 1160 Node* StoreMapNoWriteBarrier(Node* object, Node* map); 1161 Node* StoreObjectFieldRoot(Node* object, int offset, 1162 Heap::RootListIndex root); 1163 // Store an array element to a FixedArray. 1164 void StoreFixedArrayElement( 1165 TNode<FixedArray> object, int index, SloppyTNode<Object> value, 1166 WriteBarrierMode barrier_mode = UPDATE_WRITE_BARRIER) { 1167 return StoreFixedArrayElement(object, IntPtrConstant(index), value, 1168 barrier_mode); 1169 } 1170 1171 Node* StoreJSArrayLength(TNode<JSArray> array, TNode<Smi> length); 1172 Node* StoreElements(TNode<Object> object, TNode<FixedArrayBase> elements); 1173 1174 void StoreFixedArrayOrPropertyArrayElement( 1175 Node* array, Node* index, Node* value, 1176 WriteBarrierMode barrier_mode = UPDATE_WRITE_BARRIER, 1177 int additional_offset = 0, 1178 ParameterMode parameter_mode = INTPTR_PARAMETERS); 1179 1180 void StoreFixedArrayElement( 1181 TNode<FixedArray> array, Node* index, SloppyTNode<Object> value, 1182 WriteBarrierMode barrier_mode = UPDATE_WRITE_BARRIER, 1183 int additional_offset = 0, 1184 ParameterMode parameter_mode = INTPTR_PARAMETERS) { 1185 FixedArrayBoundsCheck(array, index, additional_offset, parameter_mode); 1186 StoreFixedArrayOrPropertyArrayElement(array, index, value, barrier_mode, 1187 additional_offset, parameter_mode); 1188 } 1189 1190 void StorePropertyArrayElement( 1191 TNode<PropertyArray> array, Node* index, SloppyTNode<Object> value, 1192 WriteBarrierMode barrier_mode = UPDATE_WRITE_BARRIER, 1193 int additional_offset = 0, 1194 ParameterMode parameter_mode = INTPTR_PARAMETERS) { 1195 StoreFixedArrayOrPropertyArrayElement(array, index, value, barrier_mode, 1196 additional_offset, parameter_mode); 1197 } 1198 1199 void StoreFixedArrayElementSmi( 1200 TNode<FixedArray> array, TNode<Smi> index, TNode<Object> value, 1201 WriteBarrierMode barrier_mode = UPDATE_WRITE_BARRIER) { 1202 StoreFixedArrayElement(array, index, value, barrier_mode, 0, 1203 SMI_PARAMETERS); 1204 } 1205 1206 void StoreFixedDoubleArrayElement( 1207 TNode<FixedDoubleArray> object, Node* index, TNode<Float64T> value, 1208 ParameterMode parameter_mode = INTPTR_PARAMETERS); 1209 1210 Node* StoreFeedbackVectorSlot( 1211 Node* object, Node* index, Node* value, 1212 WriteBarrierMode barrier_mode = UPDATE_WRITE_BARRIER, 1213 int additional_offset = 0, 1214 ParameterMode parameter_mode = INTPTR_PARAMETERS); 1215 1216 void EnsureArrayLengthWritable(TNode<Map> map, Label* bailout); 1217 1218 // EnsureArrayPushable verifies that receiver with this map is: 1219 // 1. Is not a prototype. 1220 // 2. Is not a dictionary. 1221 // 3. Has a writeable length property. 1222 // It returns ElementsKind as a node for further division into cases. 1223 TNode<Int32T> EnsureArrayPushable(TNode<Map> map, Label* bailout); 1224 1225 void TryStoreArrayElement(ElementsKind kind, ParameterMode mode, 1226 Label* bailout, Node* elements, Node* index, 1227 Node* value); 1228 // Consumes args into the array, and returns tagged new length. 1229 TNode<Smi> BuildAppendJSArray(ElementsKind kind, SloppyTNode<JSArray> array, 1230 CodeStubArguments* args, 1231 TVariable<IntPtrT>* arg_index, Label* bailout); 1232 // Pushes value onto the end of array. 1233 void BuildAppendJSArray(ElementsKind kind, Node* array, Node* value, 1234 Label* bailout); 1235 1236 void StoreFieldsNoWriteBarrier(Node* start_address, Node* end_address, 1237 Node* value); 1238 1239 Node* AllocateCellWithValue(Node* value, 1240 WriteBarrierMode mode = UPDATE_WRITE_BARRIER); 1241 Node* AllocateSmiCell(int value = 0) { 1242 return AllocateCellWithValue(SmiConstant(value), SKIP_WRITE_BARRIER); 1243 } 1244 1245 Node* LoadCellValue(Node* cell); 1246 1247 Node* StoreCellValue(Node* cell, Node* value, 1248 WriteBarrierMode mode = UPDATE_WRITE_BARRIER); 1249 1250 // Allocate a HeapNumber without initializing its value. 1251 TNode<HeapNumber> AllocateHeapNumber(); 1252 // Allocate a HeapNumber with a specific value. 1253 TNode<HeapNumber> AllocateHeapNumberWithValue(SloppyTNode<Float64T> value); AllocateHeapNumberWithValue(double value)1254 TNode<HeapNumber> AllocateHeapNumberWithValue(double value) { 1255 return AllocateHeapNumberWithValue(Float64Constant(value)); 1256 } 1257 1258 // Allocate a MutableHeapNumber with a specific value. 1259 TNode<MutableHeapNumber> AllocateMutableHeapNumberWithValue( 1260 SloppyTNode<Float64T> value); 1261 1262 // Allocate a BigInt with {length} digits. Sets the sign bit to {false}. 1263 // Does not initialize the digits. 1264 TNode<BigInt> AllocateBigInt(TNode<IntPtrT> length); 1265 // Like above, but allowing custom bitfield initialization. 1266 TNode<BigInt> AllocateRawBigInt(TNode<IntPtrT> length); 1267 void StoreBigIntBitfield(TNode<BigInt> bigint, TNode<WordT> bitfield); 1268 void StoreBigIntDigit(TNode<BigInt> bigint, int digit_index, 1269 TNode<UintPtrT> digit); 1270 TNode<WordT> LoadBigIntBitfield(TNode<BigInt> bigint); 1271 TNode<UintPtrT> LoadBigIntDigit(TNode<BigInt> bigint, int digit_index); 1272 1273 // Allocate a SeqOneByteString with the given length. 1274 TNode<String> AllocateSeqOneByteString(int length, 1275 AllocationFlags flags = kNone); 1276 TNode<String> AllocateSeqOneByteString(Node* context, TNode<Smi> length, 1277 AllocationFlags flags = kNone); 1278 // Allocate a SeqTwoByteString with the given length. 1279 TNode<String> AllocateSeqTwoByteString(int length, 1280 AllocationFlags flags = kNone); 1281 TNode<String> AllocateSeqTwoByteString(Node* context, TNode<Smi> length, 1282 AllocationFlags flags = kNone); 1283 1284 // Allocate a SlicedOneByteString with the given length, parent and offset. 1285 // |length| and |offset| are expected to be tagged. 1286 1287 TNode<String> AllocateSlicedOneByteString(TNode<Smi> length, 1288 TNode<String> parent, 1289 TNode<Smi> offset); 1290 // Allocate a SlicedTwoByteString with the given length, parent and offset. 1291 // |length| and |offset| are expected to be tagged. 1292 TNode<String> AllocateSlicedTwoByteString(TNode<Smi> length, 1293 TNode<String> parent, 1294 TNode<Smi> offset); 1295 1296 // Allocate a one-byte ConsString with the given length, first and second 1297 // parts. |length| is expected to be tagged, and |first| and |second| are 1298 // expected to be one-byte strings. 1299 TNode<String> AllocateOneByteConsString(TNode<Smi> length, 1300 TNode<String> first, 1301 TNode<String> second, 1302 AllocationFlags flags = kNone); 1303 // Allocate a two-byte ConsString with the given length, first and second 1304 // parts. |length| is expected to be tagged, and |first| and |second| are 1305 // expected to be two-byte strings. 1306 TNode<String> AllocateTwoByteConsString(TNode<Smi> length, 1307 TNode<String> first, 1308 TNode<String> second, 1309 AllocationFlags flags = kNone); 1310 1311 // Allocate an appropriate one- or two-byte ConsString with the first and 1312 // second parts specified by |left| and |right|. 1313 TNode<String> NewConsString(Node* context, TNode<Smi> length, 1314 TNode<String> left, TNode<String> right, 1315 AllocationFlags flags = kNone); 1316 1317 TNode<NameDictionary> AllocateNameDictionary(int at_least_space_for); 1318 TNode<NameDictionary> AllocateNameDictionary( 1319 TNode<IntPtrT> at_least_space_for); 1320 TNode<NameDictionary> AllocateNameDictionaryWithCapacity( 1321 TNode<IntPtrT> capacity); 1322 TNode<NameDictionary> CopyNameDictionary(TNode<NameDictionary> dictionary, 1323 Label* large_object_fallback); 1324 1325 template <typename CollectionType> 1326 Node* AllocateOrderedHashTable(); 1327 1328 // Builds code that finds OrderedHashTable entry for a key with hash code 1329 // {hash} with using the comparison code generated by {key_compare}. The code 1330 // jumps to {entry_found} if the key is found, or to {not_found} if the key 1331 // was not found. In the {entry_found} branch, the variable 1332 // entry_start_position will be bound to the index of the entry (relative to 1333 // OrderedHashTable::kHashTableStartIndex). 1334 // 1335 // The {CollectionType} template parameter stands for the particular instance 1336 // of OrderedHashTable, it should be OrderedHashMap or OrderedHashSet. 1337 template <typename CollectionType> 1338 void FindOrderedHashTableEntry( 1339 Node* table, Node* hash, 1340 std::function<void(Node*, Label*, Label*)> key_compare, 1341 Variable* entry_start_position, Label* entry_found, Label* not_found); 1342 1343 template <typename CollectionType> 1344 TNode<CollectionType> AllocateSmallOrderedHashTable(TNode<IntPtrT> capacity); 1345 1346 Node* AllocateStruct(Node* map, AllocationFlags flags = kNone); 1347 void InitializeStructBody(Node* object, Node* map, Node* size, 1348 int start_offset = Struct::kHeaderSize); 1349 1350 Node* AllocateJSObjectFromMap( 1351 Node* map, Node* properties = nullptr, Node* elements = nullptr, 1352 AllocationFlags flags = kNone, 1353 SlackTrackingMode slack_tracking_mode = kNoSlackTracking); 1354 1355 void InitializeJSObjectFromMap( 1356 Node* object, Node* map, Node* instance_size, Node* properties = nullptr, 1357 Node* elements = nullptr, 1358 SlackTrackingMode slack_tracking_mode = kNoSlackTracking); 1359 1360 void InitializeJSObjectBodyWithSlackTracking(Node* object, Node* map, 1361 Node* instance_size); 1362 void InitializeJSObjectBodyNoSlackTracking( 1363 Node* object, Node* map, Node* instance_size, 1364 int start_offset = JSObject::kHeaderSize); 1365 1366 // Allocate a JSArray without elements and initialize the header fields. 1367 Node* AllocateUninitializedJSArrayWithoutElements( 1368 Node* array_map, Node* length, Node* allocation_site = nullptr); 1369 // Allocate and return a JSArray with initialized header fields and its 1370 // uninitialized elements. 1371 // The ParameterMode argument is only used for the capacity parameter. 1372 std::pair<Node*, Node*> AllocateUninitializedJSArrayWithElements( 1373 ElementsKind kind, Node* array_map, Node* length, Node* allocation_site, 1374 Node* capacity, ParameterMode capacity_mode = INTPTR_PARAMETERS); 1375 // Allocate a JSArray and fill elements with the hole. 1376 // The ParameterMode argument is only used for the capacity parameter. 1377 Node* AllocateJSArray(ElementsKind kind, Node* array_map, Node* capacity, 1378 Node* length, Node* allocation_site = nullptr, 1379 ParameterMode capacity_mode = INTPTR_PARAMETERS); 1380 AllocateJSArray(ElementsKind kind,TNode<Map> array_map,TNode<Smi> capacity,TNode<Smi> length)1381 Node* AllocateJSArray(ElementsKind kind, TNode<Map> array_map, 1382 TNode<Smi> capacity, TNode<Smi> length) { 1383 return AllocateJSArray(kind, array_map, capacity, length, nullptr, 1384 SMI_PARAMETERS); 1385 } 1386 AllocateJSArray(ElementsKind kind,TNode<Map> array_map,TNode<IntPtrT> capacity,TNode<Smi> length)1387 Node* AllocateJSArray(ElementsKind kind, TNode<Map> array_map, 1388 TNode<IntPtrT> capacity, TNode<Smi> length) { 1389 return AllocateJSArray(kind, array_map, capacity, length, nullptr, 1390 INTPTR_PARAMETERS); 1391 } 1392 1393 Node* CloneFastJSArray(Node* context, Node* array, 1394 ParameterMode mode = INTPTR_PARAMETERS, 1395 Node* allocation_site = nullptr); 1396 1397 Node* ExtractFastJSArray(Node* context, Node* array, Node* begin, Node* count, 1398 ParameterMode mode = INTPTR_PARAMETERS, 1399 Node* capacity = nullptr, 1400 Node* allocation_site = nullptr); 1401 1402 TNode<FixedArrayBase> AllocateFixedArray( 1403 ElementsKind kind, Node* capacity, ParameterMode mode = INTPTR_PARAMETERS, 1404 AllocationFlags flags = kNone, 1405 SloppyTNode<Map> fixed_array_map = nullptr); 1406 1407 TNode<FixedArrayBase> AllocateFixedArray( 1408 ElementsKind kind, TNode<IntPtrT> capacity, AllocationFlags flags, 1409 SloppyTNode<Map> fixed_array_map = nullptr) { 1410 return AllocateFixedArray(kind, capacity, INTPTR_PARAMETERS, flags, 1411 fixed_array_map); 1412 } 1413 AllocateZeroedFixedArray(TNode<IntPtrT> capacity)1414 TNode<FixedArray> AllocateZeroedFixedArray(TNode<IntPtrT> capacity) { 1415 TNode<FixedArray> result = UncheckedCast<FixedArray>( 1416 AllocateFixedArray(PACKED_ELEMENTS, capacity, 1417 AllocationFlag::kAllowLargeObjectAllocation)); 1418 FillFixedArrayWithSmiZero(result, capacity); 1419 return result; 1420 } 1421 AllocateZeroedFixedDoubleArray(TNode<IntPtrT> capacity)1422 TNode<FixedDoubleArray> AllocateZeroedFixedDoubleArray( 1423 TNode<IntPtrT> capacity) { 1424 TNode<FixedDoubleArray> result = UncheckedCast<FixedDoubleArray>( 1425 AllocateFixedArray(FLOAT64_ELEMENTS, capacity, 1426 AllocationFlag::kAllowLargeObjectAllocation)); 1427 FillFixedDoubleArrayWithZero(result, capacity); 1428 return result; 1429 } 1430 1431 Node* AllocatePropertyArray(Node* capacity, 1432 ParameterMode mode = INTPTR_PARAMETERS, 1433 AllocationFlags flags = kNone); 1434 1435 // Perform CreateArrayIterator (ES #sec-createarrayiterator). 1436 TNode<JSArrayIterator> CreateArrayIterator(TNode<Context> context, 1437 TNode<Object> object, 1438 IterationKind mode); 1439 1440 Node* AllocateJSIteratorResult(Node* context, Node* value, Node* done); 1441 Node* AllocateJSIteratorResultForEntry(Node* context, Node* key, Node* value); 1442 1443 Node* ArraySpeciesCreate(TNode<Context> context, TNode<Object> originalArray, 1444 TNode<Number> len); 1445 1446 void FillFixedArrayWithValue(ElementsKind kind, Node* array, Node* from_index, 1447 Node* to_index, 1448 Heap::RootListIndex value_root_index, 1449 ParameterMode mode = INTPTR_PARAMETERS); 1450 1451 // Uses memset to effectively initialize the given FixedArray with zeroes. 1452 void FillFixedArrayWithSmiZero(TNode<FixedArray> array, 1453 TNode<IntPtrT> length); 1454 void FillFixedDoubleArrayWithZero(TNode<FixedDoubleArray> array, 1455 TNode<IntPtrT> length); 1456 1457 void FillPropertyArrayWithUndefined(Node* array, Node* from_index, 1458 Node* to_index, 1459 ParameterMode mode = INTPTR_PARAMETERS); 1460 1461 void CopyPropertyArrayValues( 1462 Node* from_array, Node* to_array, Node* length, 1463 WriteBarrierMode barrier_mode = UPDATE_WRITE_BARRIER, 1464 ParameterMode mode = INTPTR_PARAMETERS); 1465 1466 // Copies all elements from |from_array| of |length| size to 1467 // |to_array| of the same size respecting the elements kind. 1468 void CopyFixedArrayElements( 1469 ElementsKind kind, Node* from_array, Node* to_array, Node* length, 1470 WriteBarrierMode barrier_mode = UPDATE_WRITE_BARRIER, 1471 ParameterMode mode = INTPTR_PARAMETERS) { 1472 CopyFixedArrayElements(kind, from_array, kind, to_array, 1473 IntPtrOrSmiConstant(0, mode), length, length, 1474 barrier_mode, mode); 1475 } 1476 1477 // Copies |element_count| elements from |from_array| starting from element 1478 // zero to |to_array| of |capacity| size respecting both array's elements 1479 // kinds. 1480 void CopyFixedArrayElements( 1481 ElementsKind from_kind, Node* from_array, ElementsKind to_kind, 1482 Node* to_array, Node* element_count, Node* capacity, 1483 WriteBarrierMode barrier_mode = UPDATE_WRITE_BARRIER, 1484 ParameterMode mode = INTPTR_PARAMETERS) { 1485 CopyFixedArrayElements(from_kind, from_array, to_kind, to_array, 1486 IntPtrOrSmiConstant(0, mode), element_count, 1487 capacity, barrier_mode, mode); 1488 } 1489 1490 // Copies |element_count| elements from |from_array| starting from element 1491 // |first_element| to |to_array| of |capacity| size respecting both array's 1492 // elements kinds. 1493 void CopyFixedArrayElements( 1494 ElementsKind from_kind, Node* from_array, ElementsKind to_kind, 1495 Node* to_array, Node* first_element, Node* element_count, Node* capacity, 1496 WriteBarrierMode barrier_mode = UPDATE_WRITE_BARRIER, 1497 ParameterMode mode = INTPTR_PARAMETERS); 1498 1499 void CopyFixedArrayElements( 1500 ElementsKind from_kind, TNode<FixedArrayBase> from_array, 1501 ElementsKind to_kind, TNode<FixedArrayBase> to_array, 1502 TNode<Smi> first_element, TNode<Smi> element_count, TNode<Smi> capacity, 1503 WriteBarrierMode barrier_mode = UPDATE_WRITE_BARRIER) { 1504 CopyFixedArrayElements(from_kind, from_array, to_kind, to_array, 1505 first_element, element_count, capacity, barrier_mode, 1506 SMI_PARAMETERS); 1507 } 1508 1509 TNode<FixedArray> HeapObjectToFixedArray(TNode<HeapObject> base, 1510 Label* cast_fail); 1511 HeapObjectToFixedDoubleArray(TNode<HeapObject> base,Label * cast_fail)1512 TNode<FixedDoubleArray> HeapObjectToFixedDoubleArray(TNode<HeapObject> base, 1513 Label* cast_fail) { 1514 GotoIf(WordNotEqual(LoadMap(base), 1515 LoadRoot(Heap::kFixedDoubleArrayMapRootIndex)), 1516 cast_fail); 1517 return UncheckedCast<FixedDoubleArray>(base); 1518 } 1519 1520 enum class ExtractFixedArrayFlag { 1521 kFixedArrays = 1, 1522 kFixedDoubleArrays = 2, 1523 kDontCopyCOW = 4, 1524 kNewSpaceAllocationOnly = 8, 1525 kAllFixedArrays = kFixedArrays | kFixedDoubleArrays, 1526 kAllFixedArraysDontCopyCOW = kAllFixedArrays | kDontCopyCOW 1527 }; 1528 1529 typedef base::Flags<ExtractFixedArrayFlag> ExtractFixedArrayFlags; 1530 1531 // Copy a portion of an existing FixedArray or FixedDoubleArray into a new 1532 // FixedArray, including special appropriate handling for empty arrays and COW 1533 // arrays. 1534 // 1535 // * |source| is either a FixedArray or FixedDoubleArray from which to copy 1536 // elements. 1537 // * |first| is the starting element index to copy from, if nullptr is passed 1538 // then index zero is used by default. 1539 // * |count| is the number of elements to copy out of the source array 1540 // starting from and including the element indexed by |start|. If |count| is 1541 // nullptr, then all of the elements from |start| to the end of |source| are 1542 // copied. 1543 // * |capacity| determines the size of the allocated result array, with 1544 // |capacity| >= |count|. If |capacity| is nullptr, then |count| is used as 1545 // the destination array's capacity. 1546 // * |extract_flags| determines whether FixedArrays, FixedDoubleArrays or both 1547 // are detected and copied. Although it's always correct to pass 1548 // kAllFixedArrays, the generated code is more compact and efficient if the 1549 // caller can specify whether only FixedArrays or FixedDoubleArrays will be 1550 // passed as the |source| parameter. 1551 // * |parameter_mode| determines the parameter mode of |first|, |count| and 1552 // |capacity|. 1553 TNode<FixedArrayBase> ExtractFixedArray( 1554 Node* source, Node* first, Node* count = nullptr, 1555 Node* capacity = nullptr, 1556 ExtractFixedArrayFlags extract_flags = 1557 ExtractFixedArrayFlag::kAllFixedArrays, 1558 ParameterMode parameter_mode = INTPTR_PARAMETERS); 1559 1560 TNode<FixedArrayBase> ExtractFixedArray( 1561 TNode<FixedArrayBase> source, TNode<Smi> first, TNode<Smi> count, 1562 TNode<Smi> capacity, 1563 ExtractFixedArrayFlags extract_flags = 1564 ExtractFixedArrayFlag::kAllFixedArrays) { 1565 return ExtractFixedArray(source, first, count, capacity, extract_flags, 1566 SMI_PARAMETERS); 1567 } 1568 1569 // Copy the entire contents of a FixedArray or FixedDoubleArray to a new 1570 // array, including special appropriate handling for empty arrays and COW 1571 // arrays. 1572 // 1573 // * |source| is either a FixedArray or FixedDoubleArray from which to copy 1574 // elements. 1575 // * |extract_flags| determines whether FixedArrays, FixedDoubleArrays or both 1576 // are detected and copied. Although it's always correct to pass 1577 // kAllFixedArrays, the generated code is more compact and efficient if the 1578 // caller can specify whether only FixedArrays or FixedDoubleArrays will be 1579 // passed as the |source| parameter. 1580 Node* CloneFixedArray(Node* source, 1581 ExtractFixedArrayFlags flags = 1582 ExtractFixedArrayFlag::kAllFixedArraysDontCopyCOW) { 1583 ParameterMode mode = OptimalParameterMode(); 1584 return ExtractFixedArray(source, IntPtrOrSmiConstant(0, mode), nullptr, 1585 nullptr, flags, mode); 1586 } 1587 1588 // Copies |character_count| elements from |from_string| to |to_string| 1589 // starting at the |from_index|'th character. |from_string| and |to_string| 1590 // can either be one-byte strings or two-byte strings, although if 1591 // |from_string| is two-byte, then |to_string| must be two-byte. 1592 // |from_index|, |to_index| and |character_count| must be intptr_ts s.t. 0 <= 1593 // |from_index| <= |from_index| + |character_count| <= from_string.length and 1594 // 0 <= |to_index| <= |to_index| + |character_count| <= to_string.length. 1595 void CopyStringCharacters(Node* from_string, Node* to_string, 1596 TNode<IntPtrT> from_index, TNode<IntPtrT> to_index, 1597 TNode<IntPtrT> character_count, 1598 String::Encoding from_encoding, 1599 String::Encoding to_encoding); 1600 1601 // Loads an element from |array| of |from_kind| elements by given |offset| 1602 // (NOTE: not index!), does a hole check if |if_hole| is provided and 1603 // converts the value so that it becomes ready for storing to array of 1604 // |to_kind| elements. 1605 Node* LoadElementAndPrepareForStore(Node* array, Node* offset, 1606 ElementsKind from_kind, 1607 ElementsKind to_kind, Label* if_hole); 1608 1609 Node* CalculateNewElementsCapacity(Node* old_capacity, 1610 ParameterMode mode = INTPTR_PARAMETERS); 1611 1612 // Tries to grow the |elements| array of given |object| to store the |key| 1613 // or bails out if the growing gap is too big. Returns new elements. 1614 Node* TryGrowElementsCapacity(Node* object, Node* elements, ElementsKind kind, 1615 Node* key, Label* bailout); 1616 1617 // Tries to grow the |capacity|-length |elements| array of given |object| 1618 // to store the |key| or bails out if the growing gap is too big. Returns 1619 // new elements. 1620 Node* TryGrowElementsCapacity(Node* object, Node* elements, ElementsKind kind, 1621 Node* key, Node* capacity, ParameterMode mode, 1622 Label* bailout); 1623 1624 // Grows elements capacity of given object. Returns new elements. 1625 Node* GrowElementsCapacity(Node* object, Node* elements, 1626 ElementsKind from_kind, ElementsKind to_kind, 1627 Node* capacity, Node* new_capacity, 1628 ParameterMode mode, Label* bailout); 1629 1630 // Given a need to grow by |growth|, allocate an appropriate new capacity 1631 // if necessary, and return a new elements FixedArray object. Label |bailout| 1632 // is followed for allocation failure. 1633 void PossiblyGrowElementsCapacity(ParameterMode mode, ElementsKind kind, 1634 Node* array, Node* length, 1635 Variable* var_elements, Node* growth, 1636 Label* bailout); 1637 1638 // Allocation site manipulation 1639 void InitializeAllocationMemento(Node* base_allocation, 1640 Node* base_allocation_size, 1641 Node* allocation_site); 1642 1643 Node* TryTaggedToFloat64(Node* value, Label* if_valueisnotnumber); 1644 Node* TruncateTaggedToFloat64(Node* context, Node* value); 1645 Node* TruncateTaggedToWord32(Node* context, Node* value); 1646 void TaggedToWord32OrBigInt(Node* context, Node* value, Label* if_number, 1647 Variable* var_word32, Label* if_bigint, 1648 Variable* var_bigint); 1649 void TaggedToWord32OrBigIntWithFeedback( 1650 Node* context, Node* value, Label* if_number, Variable* var_word32, 1651 Label* if_bigint, Variable* var_bigint, Variable* var_feedback); 1652 1653 // Truncate the floating point value of a HeapNumber to an Int32. 1654 Node* TruncateHeapNumberValueToWord32(Node* object); 1655 1656 // Conversions. 1657 void TryHeapNumberToSmi(TNode<HeapNumber> number, TVariable<Smi>& output, 1658 Label* if_smi); 1659 void TryFloat64ToSmi(TNode<Float64T> number, TVariable<Smi>& output, 1660 Label* if_smi); 1661 TNode<Number> ChangeFloat64ToTagged(SloppyTNode<Float64T> value); 1662 TNode<Number> ChangeInt32ToTagged(SloppyTNode<Int32T> value); 1663 TNode<Number> ChangeUint32ToTagged(SloppyTNode<Uint32T> value); 1664 TNode<Uint32T> ChangeNumberToUint32(TNode<Number> value); 1665 TNode<Float64T> ChangeNumberToFloat64(SloppyTNode<Number> value); 1666 TNode<UintPtrT> ChangeNonnegativeNumberToUintPtr(TNode<Number> value); 1667 1668 void TaggedToNumeric(Node* context, Node* value, Label* done, 1669 Variable* var_numeric); 1670 void TaggedToNumericWithFeedback(Node* context, Node* value, Label* done, 1671 Variable* var_numeric, 1672 Variable* var_feedback); 1673 1674 TNode<WordT> TimesPointerSize(SloppyTNode<WordT> value); TimesPointerSize(TNode<IntPtrT> value)1675 TNode<IntPtrT> TimesPointerSize(TNode<IntPtrT> value) { 1676 return Signed(TimesPointerSize(implicit_cast<TNode<WordT>>(value))); 1677 } TimesPointerSize(TNode<UintPtrT> value)1678 TNode<UintPtrT> TimesPointerSize(TNode<UintPtrT> value) { 1679 return Unsigned(TimesPointerSize(implicit_cast<TNode<WordT>>(value))); 1680 } 1681 TNode<WordT> TimesDoubleSize(SloppyTNode<WordT> value); TimesDoubleSize(TNode<UintPtrT> value)1682 TNode<UintPtrT> TimesDoubleSize(TNode<UintPtrT> value) { 1683 return Unsigned(TimesDoubleSize(implicit_cast<TNode<WordT>>(value))); 1684 } TimesDoubleSize(TNode<IntPtrT> value)1685 TNode<IntPtrT> TimesDoubleSize(TNode<IntPtrT> value) { 1686 return Signed(TimesDoubleSize(implicit_cast<TNode<WordT>>(value))); 1687 } 1688 1689 // Type conversions. 1690 // Throws a TypeError for {method_name} if {value} is not coercible to Object, 1691 // or returns the {value} converted to a String otherwise. 1692 TNode<String> ToThisString(Node* context, Node* value, 1693 char const* method_name); 1694 // Throws a TypeError for {method_name} if {value} is neither of the given 1695 // {primitive_type} nor a JSValue wrapping a value of {primitive_type}, or 1696 // returns the {value} (or wrapped value) otherwise. 1697 Node* ToThisValue(Node* context, Node* value, PrimitiveType primitive_type, 1698 char const* method_name); 1699 1700 // Throws a TypeError for {method_name} if {value} is not of the given 1701 // instance type. Returns {value}'s map. 1702 Node* ThrowIfNotInstanceType(Node* context, Node* value, 1703 InstanceType instance_type, 1704 char const* method_name); 1705 // Throws a TypeError for {method_name} if {value} is not a JSReceiver. 1706 // Returns the {value}'s map. 1707 Node* ThrowIfNotJSReceiver(Node* context, Node* value, 1708 MessageTemplate::Template msg_template, 1709 const char* method_name = nullptr); 1710 1711 void ThrowRangeError(Node* context, MessageTemplate::Template message, 1712 Node* arg0 = nullptr, Node* arg1 = nullptr, 1713 Node* arg2 = nullptr); 1714 void ThrowTypeError(Node* context, MessageTemplate::Template message, 1715 char const* arg0 = nullptr, char const* arg1 = nullptr); 1716 void ThrowTypeError(Node* context, MessageTemplate::Template message, 1717 Node* arg0, Node* arg1 = nullptr, Node* arg2 = nullptr); 1718 1719 // Type checks. 1720 // Check whether the map is for an object with special properties, such as a 1721 // JSProxy or an object with interceptors. 1722 TNode<BoolT> InstanceTypeEqual(SloppyTNode<Int32T> instance_type, int type); 1723 TNode<BoolT> IsAccessorInfo(SloppyTNode<HeapObject> object); 1724 TNode<BoolT> IsAccessorPair(SloppyTNode<HeapObject> object); 1725 TNode<BoolT> IsAllocationSite(SloppyTNode<HeapObject> object); 1726 TNode<BoolT> IsAnyHeapNumber(SloppyTNode<HeapObject> object); 1727 TNode<BoolT> IsNoElementsProtectorCellInvalid(); 1728 TNode<BoolT> IsBigIntInstanceType(SloppyTNode<Int32T> instance_type); 1729 TNode<BoolT> IsBigInt(SloppyTNode<HeapObject> object); 1730 TNode<BoolT> IsBoolean(SloppyTNode<HeapObject> object); 1731 TNode<BoolT> IsCallableMap(SloppyTNode<Map> map); 1732 TNode<BoolT> IsCallable(SloppyTNode<HeapObject> object); 1733 TNode<BoolT> TaggedIsCallable(TNode<Object> object); 1734 TNode<BoolT> IsCell(SloppyTNode<HeapObject> object); 1735 TNode<BoolT> IsCode(SloppyTNode<HeapObject> object); 1736 TNode<BoolT> IsConsStringInstanceType(SloppyTNode<Int32T> instance_type); 1737 TNode<BoolT> IsConstructorMap(SloppyTNode<Map> map); 1738 TNode<BoolT> IsConstructor(SloppyTNode<HeapObject> object); 1739 TNode<BoolT> IsDeprecatedMap(SloppyTNode<Map> map); 1740 TNode<BoolT> IsNameDictionary(SloppyTNode<HeapObject> object); 1741 TNode<BoolT> IsGlobalDictionary(SloppyTNode<HeapObject> object); 1742 TNode<BoolT> IsExtensibleMap(SloppyTNode<Map> map); 1743 TNode<BoolT> IsExternalStringInstanceType(SloppyTNode<Int32T> instance_type); 1744 TNode<BoolT> IsFastJSArray(SloppyTNode<Object> object, 1745 SloppyTNode<Context> context); 1746 TNode<BoolT> IsFastJSArrayWithNoCustomIteration(TNode<Object> object, 1747 TNode<Context> context); 1748 TNode<BoolT> IsFeedbackCell(SloppyTNode<HeapObject> object); 1749 TNode<BoolT> IsFeedbackVector(SloppyTNode<HeapObject> object); 1750 TNode<BoolT> IsContext(SloppyTNode<HeapObject> object); 1751 TNode<BoolT> IsFixedArray(SloppyTNode<HeapObject> object); 1752 TNode<BoolT> IsFixedArraySubclass(SloppyTNode<HeapObject> object); 1753 TNode<BoolT> IsFixedArrayWithKind(SloppyTNode<HeapObject> object, 1754 ElementsKind kind); 1755 TNode<BoolT> IsFixedArrayWithKindOrEmpty(SloppyTNode<HeapObject> object, 1756 ElementsKind kind); 1757 TNode<BoolT> IsFixedDoubleArray(SloppyTNode<HeapObject> object); 1758 TNode<BoolT> IsFixedTypedArray(SloppyTNode<HeapObject> object); 1759 TNode<BoolT> IsFunctionWithPrototypeSlotMap(SloppyTNode<Map> map); 1760 TNode<BoolT> IsHashTable(SloppyTNode<HeapObject> object); 1761 TNode<BoolT> IsEphemeronHashTable(SloppyTNode<HeapObject> object); 1762 TNode<BoolT> IsHeapNumber(SloppyTNode<HeapObject> object); 1763 TNode<BoolT> IsIndirectStringInstanceType(SloppyTNode<Int32T> instance_type); 1764 TNode<BoolT> IsJSArrayBuffer(SloppyTNode<HeapObject> object); 1765 TNode<BoolT> IsJSDataView(TNode<HeapObject> object); 1766 TNode<BoolT> IsJSArrayInstanceType(SloppyTNode<Int32T> instance_type); 1767 TNode<BoolT> IsJSArrayMap(SloppyTNode<Map> map); 1768 TNode<BoolT> IsJSArray(SloppyTNode<HeapObject> object); 1769 TNode<BoolT> IsJSArrayIterator(SloppyTNode<HeapObject> object); 1770 TNode<BoolT> IsJSAsyncGeneratorObject(SloppyTNode<HeapObject> object); 1771 TNode<BoolT> IsJSFunctionInstanceType(SloppyTNode<Int32T> instance_type); 1772 TNode<BoolT> IsAllocationSiteInstanceType(SloppyTNode<Int32T> instance_type); 1773 TNode<BoolT> IsJSFunctionMap(SloppyTNode<Map> map); 1774 TNode<BoolT> IsJSFunction(SloppyTNode<HeapObject> object); 1775 TNode<BoolT> IsJSGeneratorObject(SloppyTNode<HeapObject> object); 1776 TNode<BoolT> IsJSGlobalProxyInstanceType(SloppyTNode<Int32T> instance_type); 1777 TNode<BoolT> IsJSGlobalProxy(SloppyTNode<HeapObject> object); 1778 TNode<BoolT> IsJSObjectInstanceType(SloppyTNode<Int32T> instance_type); 1779 TNode<BoolT> IsJSObjectMap(SloppyTNode<Map> map); 1780 TNode<BoolT> IsJSObject(SloppyTNode<HeapObject> object); 1781 TNode<BoolT> IsJSPromiseMap(SloppyTNode<Map> map); 1782 TNode<BoolT> IsJSPromise(SloppyTNode<HeapObject> object); 1783 TNode<BoolT> IsJSProxy(SloppyTNode<HeapObject> object); 1784 TNode<BoolT> IsJSReceiverInstanceType(SloppyTNode<Int32T> instance_type); 1785 TNode<BoolT> IsJSReceiverMap(SloppyTNode<Map> map); 1786 TNode<BoolT> IsJSReceiver(SloppyTNode<HeapObject> object); 1787 TNode<BoolT> IsJSRegExp(SloppyTNode<HeapObject> object); 1788 TNode<BoolT> IsJSTypedArray(SloppyTNode<HeapObject> object); 1789 TNode<BoolT> IsJSValueInstanceType(SloppyTNode<Int32T> instance_type); 1790 TNode<BoolT> IsJSValueMap(SloppyTNode<Map> map); 1791 TNode<BoolT> IsJSValue(SloppyTNode<HeapObject> object); 1792 TNode<BoolT> IsMap(SloppyTNode<HeapObject> object); 1793 TNode<BoolT> IsMutableHeapNumber(SloppyTNode<HeapObject> object); 1794 TNode<BoolT> IsName(SloppyTNode<HeapObject> object); 1795 TNode<BoolT> IsNativeContext(SloppyTNode<HeapObject> object); 1796 TNode<BoolT> IsNullOrJSReceiver(SloppyTNode<HeapObject> object); 1797 TNode<BoolT> IsNullOrUndefined(SloppyTNode<Object> object); 1798 TNode<BoolT> IsNumberDictionary(SloppyTNode<HeapObject> object); 1799 TNode<BoolT> IsOneByteStringInstanceType(SloppyTNode<Int32T> instance_type); 1800 TNode<BoolT> IsPrimitiveInstanceType(SloppyTNode<Int32T> instance_type); 1801 TNode<BoolT> IsPrivateSymbol(SloppyTNode<HeapObject> object); 1802 TNode<BoolT> IsPromiseCapability(SloppyTNode<HeapObject> object); 1803 TNode<BoolT> IsPropertyArray(SloppyTNode<HeapObject> object); 1804 TNode<BoolT> IsPropertyCell(SloppyTNode<HeapObject> object); 1805 TNode<BoolT> IsPrototypeInitialArrayPrototype(SloppyTNode<Context> context, 1806 SloppyTNode<Map> map); 1807 TNode<BoolT> IsPrototypeTypedArrayPrototype(SloppyTNode<Context> context, 1808 SloppyTNode<Map> map); 1809 TNode<BoolT> IsSequentialStringInstanceType( 1810 SloppyTNode<Int32T> instance_type); 1811 TNode<BoolT> IsShortExternalStringInstanceType( 1812 SloppyTNode<Int32T> instance_type); 1813 TNode<BoolT> IsSpecialReceiverInstanceType(TNode<Int32T> instance_type); 1814 TNode<BoolT> IsCustomElementsReceiverInstanceType( 1815 TNode<Int32T> instance_type); 1816 TNode<BoolT> IsSpecialReceiverMap(SloppyTNode<Map> map); 1817 // Returns true if the map corresponds to non-special fast or dictionary 1818 // object. 1819 TNode<BoolT> IsSimpleObjectMap(TNode<Map> map); 1820 TNode<BoolT> IsStringInstanceType(SloppyTNode<Int32T> instance_type); 1821 TNode<BoolT> IsString(SloppyTNode<HeapObject> object); 1822 TNode<BoolT> IsSymbolInstanceType(SloppyTNode<Int32T> instance_type); 1823 TNode<BoolT> IsSymbol(SloppyTNode<HeapObject> object); 1824 TNode<BoolT> IsUndetectableMap(SloppyTNode<Map> map); 1825 TNode<BoolT> IsNotWeakFixedArraySubclass(SloppyTNode<HeapObject> object); 1826 TNode<BoolT> IsZeroOrContext(SloppyTNode<Object> object); 1827 IsSharedFunctionInfo(Node * object)1828 inline Node* IsSharedFunctionInfo(Node* object) { 1829 return IsSharedFunctionInfoMap(LoadMap(object)); 1830 } 1831 1832 TNode<BoolT> IsPromiseResolveProtectorCellInvalid(); 1833 TNode<BoolT> IsPromiseThenProtectorCellInvalid(); 1834 TNode<BoolT> IsArraySpeciesProtectorCellInvalid(); 1835 TNode<BoolT> IsTypedArraySpeciesProtectorCellInvalid(); 1836 TNode<BoolT> IsPromiseSpeciesProtectorCellInvalid(); 1837 1838 // True iff |object| is a Smi or a HeapNumber. 1839 TNode<BoolT> IsNumber(SloppyTNode<Object> object); 1840 // True iff |object| is a Smi or a HeapNumber or a BigInt. 1841 TNode<BoolT> IsNumeric(SloppyTNode<Object> object); 1842 1843 // True iff |number| is either a Smi, or a HeapNumber whose value is not 1844 // within Smi range. 1845 TNode<BoolT> IsNumberNormalized(SloppyTNode<Number> number); 1846 TNode<BoolT> IsNumberPositive(SloppyTNode<Number> number); 1847 TNode<BoolT> IsHeapNumberPositive(TNode<HeapNumber> number); 1848 1849 // True iff {number} is non-negative and less or equal than 2**53-1. 1850 TNode<BoolT> IsNumberNonNegativeSafeInteger(TNode<Number> number); 1851 1852 // True iff {number} represents an integer value. 1853 TNode<BoolT> IsInteger(TNode<Object> number); 1854 TNode<BoolT> IsInteger(TNode<HeapNumber> number); 1855 1856 // True iff abs({number}) <= 2**53 -1 1857 TNode<BoolT> IsSafeInteger(TNode<Object> number); 1858 TNode<BoolT> IsSafeInteger(TNode<HeapNumber> number); 1859 1860 // True iff {number} represents a valid uint32t value. 1861 TNode<BoolT> IsHeapNumberUint32(TNode<HeapNumber> number); 1862 1863 // True iff {number} is a positive number and a valid array index in the range 1864 // [0, 2^32-1). 1865 TNode<BoolT> IsNumberArrayIndex(TNode<Number> number); 1866 1867 Node* FixedArraySizeDoesntFitInNewSpace( 1868 Node* element_count, int base_size = FixedArray::kHeaderSize, 1869 ParameterMode mode = INTPTR_PARAMETERS); 1870 1871 // ElementsKind helpers: ElementsKindEqual(TNode<Int32T> a,TNode<Int32T> b)1872 TNode<BoolT> ElementsKindEqual(TNode<Int32T> a, TNode<Int32T> b) { 1873 return Word32Equal(a, b); 1874 } ElementsKindEqual(ElementsKind a,ElementsKind b)1875 bool ElementsKindEqual(ElementsKind a, ElementsKind b) { return a == b; } 1876 Node* IsFastElementsKind(Node* elements_kind); IsFastElementsKind(ElementsKind kind)1877 bool IsFastElementsKind(ElementsKind kind) { 1878 return v8::internal::IsFastElementsKind(kind); 1879 } IsDictionaryElementsKind(TNode<Int32T> elements_kind)1880 TNode<BoolT> IsDictionaryElementsKind(TNode<Int32T> elements_kind) { 1881 return ElementsKindEqual(elements_kind, Int32Constant(DICTIONARY_ELEMENTS)); 1882 } 1883 TNode<BoolT> IsDoubleElementsKind(TNode<Int32T> elements_kind); IsDoubleElementsKind(ElementsKind kind)1884 bool IsDoubleElementsKind(ElementsKind kind) { 1885 return v8::internal::IsDoubleElementsKind(kind); 1886 } 1887 Node* IsFastSmiOrTaggedElementsKind(Node* elements_kind); 1888 Node* IsFastSmiElementsKind(Node* elements_kind); 1889 Node* IsHoleyFastElementsKind(Node* elements_kind); 1890 Node* IsElementsKindGreaterThan(Node* target_kind, 1891 ElementsKind reference_kind); 1892 1893 // String helpers. 1894 // Load a character from a String (might flatten a ConsString). 1895 TNode<Int32T> StringCharCodeAt(SloppyTNode<String> string, 1896 SloppyTNode<IntPtrT> index); 1897 // Return the single character string with only {code}. 1898 TNode<String> StringFromSingleCharCode(TNode<Int32T> code); 1899 1900 // Return a new string object which holds a substring containing the range 1901 // [from,to[ of string. 1902 TNode<String> SubString(TNode<String> string, TNode<IntPtrT> from, 1903 TNode<IntPtrT> to); 1904 1905 // Return a new string object produced by concatenating |first| with |second|. 1906 TNode<String> StringAdd(Node* context, TNode<String> first, 1907 TNode<String> second, AllocationFlags flags = kNone); 1908 1909 // Check if |string| is an indirect (thin or flat cons) string type that can 1910 // be dereferenced by DerefIndirectString. 1911 void BranchIfCanDerefIndirectString(Node* string, Node* instance_type, 1912 Label* can_deref, Label* cannot_deref); 1913 // Unpack an indirect (thin or flat cons) string type. 1914 void DerefIndirectString(Variable* var_string, Node* instance_type); 1915 // Check if |var_string| has an indirect (thin or flat cons) string type, 1916 // and unpack it if so. 1917 void MaybeDerefIndirectString(Variable* var_string, Node* instance_type, 1918 Label* did_deref, Label* cannot_deref); 1919 // Check if |var_left| or |var_right| has an indirect (thin or flat cons) 1920 // string type, and unpack it/them if so. Fall through if nothing was done. 1921 void MaybeDerefIndirectStrings(Variable* var_left, Node* left_instance_type, 1922 Variable* var_right, Node* right_instance_type, 1923 Label* did_something); 1924 Node* DerefIndirectString(TNode<String> string, TNode<Int32T> instance_type, 1925 Label* cannot_deref); 1926 1927 TNode<String> StringFromSingleCodePoint(TNode<Int32T> codepoint, 1928 UnicodeEncoding encoding); 1929 1930 // Type conversion helpers. 1931 enum class BigIntHandling { kConvertToNumber, kThrow }; 1932 // Convert a String to a Number. 1933 TNode<Number> StringToNumber(TNode<String> input); 1934 // Convert a Number to a String. 1935 TNode<String> NumberToString(TNode<Number> input); 1936 // Convert an object to a name. 1937 TNode<Name> ToName(SloppyTNode<Context> context, SloppyTNode<Object> value); 1938 // Convert a Non-Number object to a Number. 1939 TNode<Number> NonNumberToNumber( 1940 SloppyTNode<Context> context, SloppyTNode<HeapObject> input, 1941 BigIntHandling bigint_handling = BigIntHandling::kThrow); 1942 // Convert a Non-Number object to a Numeric. 1943 TNode<Numeric> NonNumberToNumeric(SloppyTNode<Context> context, 1944 SloppyTNode<HeapObject> input); 1945 // Convert any object to a Number. 1946 // Conforms to ES#sec-tonumber if {bigint_handling} == kThrow. 1947 // With {bigint_handling} == kConvertToNumber, matches behavior of 1948 // tc39.github.io/proposal-bigint/#sec-number-constructor-number-value. 1949 TNode<Number> ToNumber( 1950 SloppyTNode<Context> context, SloppyTNode<Object> input, 1951 BigIntHandling bigint_handling = BigIntHandling::kThrow); 1952 TNode<Number> ToNumber_Inline(SloppyTNode<Context> context, 1953 SloppyTNode<Object> input); 1954 1955 // Try to convert an object to a BigInt. Throws on failure (e.g. for Numbers). 1956 // https://tc39.github.io/proposal-bigint/#sec-to-bigint 1957 TNode<BigInt> ToBigInt(SloppyTNode<Context> context, 1958 SloppyTNode<Object> input); 1959 1960 // Converts |input| to one of 2^32 integer values in the range 0 through 1961 // 2^32-1, inclusive. 1962 // ES#sec-touint32 1963 TNode<Number> ToUint32(SloppyTNode<Context> context, 1964 SloppyTNode<Object> input); 1965 1966 // Convert any object to a String. 1967 TNode<String> ToString(SloppyTNode<Context> context, 1968 SloppyTNode<Object> input); 1969 TNode<String> ToString_Inline(SloppyTNode<Context> context, 1970 SloppyTNode<Object> input); 1971 1972 // Convert any object to a Primitive. 1973 Node* JSReceiverToPrimitive(Node* context, Node* input); 1974 1975 TNode<JSReceiver> ToObject(SloppyTNode<Context> context, 1976 SloppyTNode<Object> input); 1977 1978 // Same as ToObject but avoids the Builtin call if |input| is already a 1979 // JSReceiver. 1980 TNode<JSReceiver> ToObject_Inline(TNode<Context> context, 1981 TNode<Object> input); 1982 1983 enum ToIntegerTruncationMode { 1984 kNoTruncation, 1985 kTruncateMinusZero, 1986 }; 1987 1988 // ES6 7.1.17 ToIndex, but jumps to range_error if the result is not a Smi. 1989 TNode<Smi> ToSmiIndex(TNode<Object> input, TNode<Context> context, 1990 Label* range_error); 1991 1992 // ES6 7.1.15 ToLength, but jumps to range_error if the result is not a Smi. 1993 TNode<Smi> ToSmiLength(TNode<Object> input, TNode<Context> context, 1994 Label* range_error); 1995 1996 // ES6 7.1.15 ToLength, but with inlined fast path. 1997 TNode<Number> ToLength_Inline(SloppyTNode<Context> context, 1998 SloppyTNode<Object> input); 1999 2000 // ES6 7.1.4 ToInteger ( argument ) 2001 TNode<Number> ToInteger_Inline(SloppyTNode<Context> context, 2002 SloppyTNode<Object> input, 2003 ToIntegerTruncationMode mode = kNoTruncation); 2004 TNode<Number> ToInteger(SloppyTNode<Context> context, 2005 SloppyTNode<Object> input, 2006 ToIntegerTruncationMode mode = kNoTruncation); 2007 2008 // Returns a node that contains a decoded (unsigned!) value of a bit 2009 // field |BitField| in |word32|. Returns result as an uint32 node. 2010 template <typename BitField> DecodeWord32(SloppyTNode<Word32T> word32)2011 TNode<Uint32T> DecodeWord32(SloppyTNode<Word32T> word32) { 2012 return DecodeWord32(word32, BitField::kShift, BitField::kMask); 2013 } 2014 2015 // Returns a node that contains a decoded (unsigned!) value of a bit 2016 // field |BitField| in |word|. Returns result as a word-size node. 2017 template <typename BitField> DecodeWord(SloppyTNode<WordT> word)2018 TNode<UintPtrT> DecodeWord(SloppyTNode<WordT> word) { 2019 return DecodeWord(word, BitField::kShift, BitField::kMask); 2020 } 2021 2022 // Returns a node that contains a decoded (unsigned!) value of a bit 2023 // field |BitField| in |word32|. Returns result as a word-size node. 2024 template <typename BitField> DecodeWordFromWord32(SloppyTNode<Word32T> word32)2025 TNode<UintPtrT> DecodeWordFromWord32(SloppyTNode<Word32T> word32) { 2026 return DecodeWord<BitField>(ChangeUint32ToWord(word32)); 2027 } 2028 2029 // Returns a node that contains a decoded (unsigned!) value of a bit 2030 // field |BitField| in |word|. Returns result as an uint32 node. 2031 template <typename BitField> DecodeWord32FromWord(SloppyTNode<WordT> word)2032 TNode<Uint32T> DecodeWord32FromWord(SloppyTNode<WordT> word) { 2033 return UncheckedCast<Uint32T>( 2034 TruncateIntPtrToInt32(Signed(DecodeWord<BitField>(word)))); 2035 } 2036 2037 // Decodes an unsigned (!) value from |word32| to an uint32 node. 2038 TNode<Uint32T> DecodeWord32(SloppyTNode<Word32T> word32, uint32_t shift, 2039 uint32_t mask); 2040 2041 // Decodes an unsigned (!) value from |word| to a word-size node. 2042 TNode<UintPtrT> DecodeWord(SloppyTNode<WordT> word, uint32_t shift, 2043 uint32_t mask); 2044 2045 // Returns a node that contains the updated values of a |BitField|. 2046 template <typename BitField> UpdateWord(TNode<WordT> word,TNode<WordT> value)2047 TNode<WordT> UpdateWord(TNode<WordT> word, TNode<WordT> value) { 2048 return UpdateWord(word, value, BitField::kShift, BitField::kMask); 2049 } 2050 2051 // Returns a node that contains the updated {value} inside {word} starting 2052 // at {shift} and fitting in {mask}. 2053 TNode<WordT> UpdateWord(TNode<WordT> word, TNode<WordT> value, uint32_t shift, 2054 uint32_t mask); 2055 2056 // Returns true if any of the |T|'s bits in given |word32| are set. 2057 template <typename T> IsSetWord32(SloppyTNode<Word32T> word32)2058 TNode<BoolT> IsSetWord32(SloppyTNode<Word32T> word32) { 2059 return IsSetWord32(word32, T::kMask); 2060 } 2061 2062 // Returns true if any of the mask's bits in given |word32| are set. IsSetWord32(SloppyTNode<Word32T> word32,uint32_t mask)2063 TNode<BoolT> IsSetWord32(SloppyTNode<Word32T> word32, uint32_t mask) { 2064 return Word32NotEqual(Word32And(word32, Int32Constant(mask)), 2065 Int32Constant(0)); 2066 } 2067 2068 // Returns true if none of the mask's bits in given |word32| are set. IsNotSetWord32(SloppyTNode<Word32T> word32,uint32_t mask)2069 TNode<BoolT> IsNotSetWord32(SloppyTNode<Word32T> word32, uint32_t mask) { 2070 return Word32Equal(Word32And(word32, Int32Constant(mask)), 2071 Int32Constant(0)); 2072 } 2073 2074 // Returns true if all of the mask's bits in a given |word32| are set. IsAllSetWord32(SloppyTNode<Word32T> word32,uint32_t mask)2075 TNode<BoolT> IsAllSetWord32(SloppyTNode<Word32T> word32, uint32_t mask) { 2076 TNode<Int32T> const_mask = Int32Constant(mask); 2077 return Word32Equal(Word32And(word32, const_mask), const_mask); 2078 } 2079 2080 // Returns true if any of the |T|'s bits in given |word| are set. 2081 template <typename T> IsSetWord(SloppyTNode<WordT> word)2082 TNode<BoolT> IsSetWord(SloppyTNode<WordT> word) { 2083 return IsSetWord(word, T::kMask); 2084 } 2085 2086 // Returns true if any of the mask's bits in given |word| are set. IsSetWord(SloppyTNode<WordT> word,uint32_t mask)2087 TNode<BoolT> IsSetWord(SloppyTNode<WordT> word, uint32_t mask) { 2088 return WordNotEqual(WordAnd(word, IntPtrConstant(mask)), IntPtrConstant(0)); 2089 } 2090 2091 // Returns true if any of the mask's bit are set in the given Smi. 2092 // Smi-encoding of the mask is performed implicitly! IsSetSmi(SloppyTNode<Smi> smi,int untagged_mask)2093 TNode<BoolT> IsSetSmi(SloppyTNode<Smi> smi, int untagged_mask) { 2094 intptr_t mask_word = bit_cast<intptr_t>(Smi::FromInt(untagged_mask)); 2095 return WordNotEqual( 2096 WordAnd(BitcastTaggedToWord(smi), IntPtrConstant(mask_word)), 2097 IntPtrConstant(0)); 2098 } 2099 2100 // Returns true if all of the |T|'s bits in given |word32| are clear. 2101 template <typename T> IsClearWord32(SloppyTNode<Word32T> word32)2102 TNode<BoolT> IsClearWord32(SloppyTNode<Word32T> word32) { 2103 return IsClearWord32(word32, T::kMask); 2104 } 2105 2106 // Returns true if all of the mask's bits in given |word32| are clear. IsClearWord32(SloppyTNode<Word32T> word32,uint32_t mask)2107 TNode<BoolT> IsClearWord32(SloppyTNode<Word32T> word32, uint32_t mask) { 2108 return Word32Equal(Word32And(word32, Int32Constant(mask)), 2109 Int32Constant(0)); 2110 } 2111 2112 // Returns true if all of the |T|'s bits in given |word| are clear. 2113 template <typename T> IsClearWord(SloppyTNode<WordT> word)2114 TNode<BoolT> IsClearWord(SloppyTNode<WordT> word) { 2115 return IsClearWord(word, T::kMask); 2116 } 2117 2118 // Returns true if all of the mask's bits in given |word| are clear. IsClearWord(SloppyTNode<WordT> word,uint32_t mask)2119 TNode<BoolT> IsClearWord(SloppyTNode<WordT> word, uint32_t mask) { 2120 return WordEqual(WordAnd(word, IntPtrConstant(mask)), IntPtrConstant(0)); 2121 } 2122 2123 void SetCounter(StatsCounter* counter, int value); 2124 void IncrementCounter(StatsCounter* counter, int delta); 2125 void DecrementCounter(StatsCounter* counter, int delta); 2126 2127 void Increment(Variable* variable, int value = 1, 2128 ParameterMode mode = INTPTR_PARAMETERS); 2129 void Decrement(Variable* variable, int value = 1, 2130 ParameterMode mode = INTPTR_PARAMETERS) { 2131 Increment(variable, -value, mode); 2132 } 2133 2134 // Generates "if (false) goto label" code. Useful for marking a label as 2135 // "live" to avoid assertion failures during graph building. In the resulting 2136 // code this check will be eliminated. 2137 void Use(Label* label); 2138 2139 // Various building blocks for stubs doing property lookups. 2140 2141 // |if_notinternalized| is optional; |if_bailout| will be used by default. 2142 void TryToName(Node* key, Label* if_keyisindex, Variable* var_index, 2143 Label* if_keyisunique, Variable* var_unique, Label* if_bailout, 2144 Label* if_notinternalized = nullptr); 2145 2146 // Performs a hash computation and string table lookup for the given string, 2147 // and jumps to: 2148 // - |if_index| if the string is an array index like "123"; |var_index| 2149 // will contain the intptr representation of that index. 2150 // - |if_internalized| if the string exists in the string table; the 2151 // internalized version will be in |var_internalized|. 2152 // - |if_not_internalized| if the string is not in the string table (but 2153 // does not add it). 2154 // - |if_bailout| for unsupported cases (e.g. uncachable array index). 2155 void TryInternalizeString(Node* string, Label* if_index, Variable* var_index, 2156 Label* if_internalized, Variable* var_internalized, 2157 Label* if_not_internalized, Label* if_bailout); 2158 2159 // Calculates array index for given dictionary entry and entry field. 2160 // See Dictionary::EntryToIndex(). 2161 template <typename Dictionary> 2162 TNode<IntPtrT> EntryToIndex(TNode<IntPtrT> entry, int field_index); 2163 template <typename Dictionary> EntryToIndex(TNode<IntPtrT> entry)2164 TNode<IntPtrT> EntryToIndex(TNode<IntPtrT> entry) { 2165 return EntryToIndex<Dictionary>(entry, Dictionary::kEntryKeyIndex); 2166 } 2167 2168 // Loads the details for the entry with the given key_index. 2169 // Returns an untagged int32. 2170 template <class ContainerType> LoadDetailsByKeyIndex(Node * container,Node * key_index)2171 TNode<Uint32T> LoadDetailsByKeyIndex(Node* container, Node* key_index) { 2172 static_assert(!std::is_same<ContainerType, DescriptorArray>::value, 2173 "Use the non-templatized version for DescriptorArray"); 2174 const int kKeyToDetailsOffset = 2175 (ContainerType::kEntryDetailsIndex - ContainerType::kEntryKeyIndex) * 2176 kPointerSize; 2177 return Unsigned(LoadAndUntagToWord32FixedArrayElement( 2178 CAST(container), key_index, kKeyToDetailsOffset)); 2179 } 2180 2181 // Loads the value for the entry with the given key_index. 2182 // Returns a tagged value. 2183 template <class ContainerType> LoadValueByKeyIndex(Node * container,Node * key_index)2184 TNode<Object> LoadValueByKeyIndex(Node* container, Node* key_index) { 2185 static_assert(!std::is_same<ContainerType, DescriptorArray>::value, 2186 "Use the non-templatized version for DescriptorArray"); 2187 const int kKeyToValueOffset = 2188 (ContainerType::kEntryValueIndex - ContainerType::kEntryKeyIndex) * 2189 kPointerSize; 2190 return LoadFixedArrayElement(CAST(container), key_index, kKeyToValueOffset); 2191 } 2192 2193 TNode<Uint32T> LoadDetailsByKeyIndex(TNode<DescriptorArray> container, 2194 TNode<IntPtrT> key_index); 2195 TNode<Object> LoadValueByKeyIndex(TNode<DescriptorArray> container, 2196 TNode<IntPtrT> key_index); 2197 TNode<MaybeObject> LoadFieldTypeByKeyIndex(TNode<DescriptorArray> container, 2198 TNode<IntPtrT> key_index); 2199 2200 // Stores the details for the entry with the given key_index. 2201 // |details| must be a Smi. 2202 template <class ContainerType> StoreDetailsByKeyIndex(TNode<ContainerType> container,TNode<IntPtrT> key_index,TNode<Smi> details)2203 void StoreDetailsByKeyIndex(TNode<ContainerType> container, 2204 TNode<IntPtrT> key_index, TNode<Smi> details) { 2205 const int kKeyToDetailsOffset = 2206 (ContainerType::kEntryDetailsIndex - ContainerType::kEntryKeyIndex) * 2207 kPointerSize; 2208 StoreFixedArrayElement(container, key_index, details, SKIP_WRITE_BARRIER, 2209 kKeyToDetailsOffset); 2210 } 2211 2212 // Stores the value for the entry with the given key_index. 2213 template <class ContainerType> 2214 void StoreValueByKeyIndex( 2215 TNode<ContainerType> container, TNode<IntPtrT> key_index, 2216 TNode<Object> value, 2217 WriteBarrierMode write_barrier = UPDATE_WRITE_BARRIER) { 2218 const int kKeyToValueOffset = 2219 (ContainerType::kEntryValueIndex - ContainerType::kEntryKeyIndex) * 2220 kPointerSize; 2221 StoreFixedArrayElement(container, key_index, value, write_barrier, 2222 kKeyToValueOffset); 2223 } 2224 2225 // Calculate a valid size for the a hash table. 2226 TNode<IntPtrT> HashTableComputeCapacity(TNode<IntPtrT> at_least_space_for); 2227 2228 template <class Dictionary> GetNumberOfElements(TNode<Dictionary> dictionary)2229 TNode<Smi> GetNumberOfElements(TNode<Dictionary> dictionary) { 2230 return CAST( 2231 LoadFixedArrayElement(dictionary, Dictionary::kNumberOfElementsIndex)); 2232 } 2233 2234 template <class Dictionary> SetNumberOfElements(TNode<Dictionary> dictionary,TNode<Smi> num_elements_smi)2235 void SetNumberOfElements(TNode<Dictionary> dictionary, 2236 TNode<Smi> num_elements_smi) { 2237 StoreFixedArrayElement(dictionary, Dictionary::kNumberOfElementsIndex, 2238 num_elements_smi, SKIP_WRITE_BARRIER); 2239 } 2240 2241 template <class Dictionary> GetNumberOfDeletedElements(TNode<Dictionary> dictionary)2242 TNode<Smi> GetNumberOfDeletedElements(TNode<Dictionary> dictionary) { 2243 return CAST(LoadFixedArrayElement( 2244 dictionary, Dictionary::kNumberOfDeletedElementsIndex)); 2245 } 2246 2247 template <class Dictionary> SetNumberOfDeletedElements(TNode<Dictionary> dictionary,TNode<Smi> num_deleted_smi)2248 void SetNumberOfDeletedElements(TNode<Dictionary> dictionary, 2249 TNode<Smi> num_deleted_smi) { 2250 StoreFixedArrayElement(dictionary, 2251 Dictionary::kNumberOfDeletedElementsIndex, 2252 num_deleted_smi, SKIP_WRITE_BARRIER); 2253 } 2254 2255 template <class Dictionary> GetCapacity(TNode<Dictionary> dictionary)2256 TNode<Smi> GetCapacity(TNode<Dictionary> dictionary) { 2257 return CAST(LoadFixedArrayElement(dictionary, Dictionary::kCapacityIndex)); 2258 } 2259 2260 template <class Dictionary> GetNextEnumerationIndex(TNode<Dictionary> dictionary)2261 TNode<Smi> GetNextEnumerationIndex(TNode<Dictionary> dictionary) { 2262 return CAST(LoadFixedArrayElement(dictionary, 2263 Dictionary::kNextEnumerationIndexIndex)); 2264 } 2265 2266 template <class Dictionary> SetNextEnumerationIndex(TNode<Dictionary> dictionary,TNode<Smi> next_enum_index_smi)2267 void SetNextEnumerationIndex(TNode<Dictionary> dictionary, 2268 TNode<Smi> next_enum_index_smi) { 2269 StoreFixedArrayElement(dictionary, Dictionary::kNextEnumerationIndexIndex, 2270 next_enum_index_smi, SKIP_WRITE_BARRIER); 2271 } 2272 2273 // Looks up an entry in a NameDictionaryBase successor. If the entry is found 2274 // control goes to {if_found} and {var_name_index} contains an index of the 2275 // key field of the entry found. If the key is not found control goes to 2276 // {if_not_found}. 2277 static const int kInlinedDictionaryProbes = 4; 2278 enum LookupMode { kFindExisting, kFindInsertionIndex }; 2279 2280 template <typename Dictionary> 2281 TNode<HeapObject> LoadName(TNode<HeapObject> key); 2282 2283 template <typename Dictionary> 2284 void NameDictionaryLookup(TNode<Dictionary> dictionary, 2285 TNode<Name> unique_name, Label* if_found, 2286 TVariable<IntPtrT>* var_name_index, 2287 Label* if_not_found, 2288 int inlined_probes = kInlinedDictionaryProbes, 2289 LookupMode mode = kFindExisting); 2290 2291 Node* ComputeIntegerHash(Node* key); 2292 Node* ComputeIntegerHash(Node* key, Node* seed); 2293 2294 void NumberDictionaryLookup(TNode<NumberDictionary> dictionary, 2295 TNode<IntPtrT> intptr_index, Label* if_found, 2296 TVariable<IntPtrT>* var_entry, 2297 Label* if_not_found); 2298 2299 TNode<Object> BasicLoadNumberDictionaryElement( 2300 TNode<NumberDictionary> dictionary, TNode<IntPtrT> intptr_index, 2301 Label* not_data, Label* if_hole); 2302 void BasicStoreNumberDictionaryElement(TNode<NumberDictionary> dictionary, 2303 TNode<IntPtrT> intptr_index, 2304 TNode<Object> value, Label* not_data, 2305 Label* if_hole, Label* read_only); 2306 2307 template <class Dictionary> 2308 void FindInsertionEntry(TNode<Dictionary> dictionary, TNode<Name> key, 2309 TVariable<IntPtrT>* var_key_index); 2310 2311 template <class Dictionary> 2312 void InsertEntry(TNode<Dictionary> dictionary, TNode<Name> key, 2313 TNode<Object> value, TNode<IntPtrT> index, 2314 TNode<Smi> enum_index); 2315 2316 template <class Dictionary> 2317 void Add(TNode<Dictionary> dictionary, TNode<Name> key, TNode<Object> value, 2318 Label* bailout); 2319 2320 // Tries to check if {object} has own {unique_name} property. 2321 void TryHasOwnProperty(Node* object, Node* map, Node* instance_type, 2322 Node* unique_name, Label* if_found, 2323 Label* if_not_found, Label* if_bailout); 2324 2325 // Operating mode for TryGetOwnProperty and CallGetterIfAccessor 2326 // kReturnAccessorPair is used when we're only getting the property descriptor 2327 enum GetOwnPropertyMode { kCallJSGetter, kReturnAccessorPair }; 2328 // Tries to get {object}'s own {unique_name} property value. If the property 2329 // is an accessor then it also calls a getter. If the property is a double 2330 // field it re-wraps value in an immutable heap number. 2331 void TryGetOwnProperty(Node* context, Node* receiver, Node* object, Node* map, 2332 Node* instance_type, Node* unique_name, 2333 Label* if_found, Variable* var_value, 2334 Label* if_not_found, Label* if_bailout); 2335 void TryGetOwnProperty(Node* context, Node* receiver, Node* object, Node* map, 2336 Node* instance_type, Node* unique_name, 2337 Label* if_found, Variable* var_value, 2338 Variable* var_details, Variable* var_raw_value, 2339 Label* if_not_found, Label* if_bailout, 2340 GetOwnPropertyMode mode); 2341 GetProperty(SloppyTNode<Context> context,SloppyTNode<Object> receiver,Handle<Name> name)2342 TNode<Object> GetProperty(SloppyTNode<Context> context, 2343 SloppyTNode<Object> receiver, Handle<Name> name) { 2344 return GetProperty(context, receiver, HeapConstant(name)); 2345 } 2346 GetProperty(SloppyTNode<Context> context,SloppyTNode<Object> receiver,SloppyTNode<Object> name)2347 TNode<Object> GetProperty(SloppyTNode<Context> context, 2348 SloppyTNode<Object> receiver, 2349 SloppyTNode<Object> name) { 2350 return CallBuiltin(Builtins::kGetProperty, context, receiver, name); 2351 } 2352 SetPropertyStrict(TNode<Context> context,TNode<Object> receiver,TNode<Object> key,TNode<Object> value)2353 TNode<Object> SetPropertyStrict(TNode<Context> context, 2354 TNode<Object> receiver, TNode<Object> key, 2355 TNode<Object> value) { 2356 return CallBuiltin(Builtins::kSetProperty, context, receiver, key, value); 2357 } 2358 2359 Node* GetMethod(Node* context, Node* object, Handle<Name> name, 2360 Label* if_null_or_undefined); 2361 2362 template <class... TArgs> CallBuiltin(Builtins::Name id,SloppyTNode<Object> context,TArgs...args)2363 TNode<Object> CallBuiltin(Builtins::Name id, SloppyTNode<Object> context, 2364 TArgs... args) { 2365 DCHECK_IMPLIES(Builtins::KindOf(id) == Builtins::TFJ, 2366 !Builtins::IsLazy(id)); 2367 return CallStub<Object>(Builtins::CallableFor(isolate(), id), context, 2368 args...); 2369 } 2370 2371 template <class... TArgs> TailCallBuiltin(Builtins::Name id,SloppyTNode<Object> context,TArgs...args)2372 void TailCallBuiltin(Builtins::Name id, SloppyTNode<Object> context, 2373 TArgs... args) { 2374 DCHECK_IMPLIES(Builtins::KindOf(id) == Builtins::TFJ, 2375 !Builtins::IsLazy(id)); 2376 return TailCallStub(Builtins::CallableFor(isolate(), id), context, args...); 2377 } 2378 2379 void LoadPropertyFromFastObject(Node* object, Node* map, 2380 TNode<DescriptorArray> descriptors, 2381 Node* name_index, Variable* var_details, 2382 Variable* var_value); 2383 2384 void LoadPropertyFromFastObject(Node* object, Node* map, 2385 TNode<DescriptorArray> descriptors, 2386 Node* name_index, Node* details, 2387 Variable* var_value); 2388 2389 void LoadPropertyFromNameDictionary(Node* dictionary, Node* entry, 2390 Variable* var_details, 2391 Variable* var_value); 2392 2393 void LoadPropertyFromGlobalDictionary(Node* dictionary, Node* entry, 2394 Variable* var_details, 2395 Variable* var_value, Label* if_deleted); 2396 2397 // Generic property lookup generator. If the {object} is fast and 2398 // {unique_name} property is found then the control goes to {if_found_fast} 2399 // label and {var_meta_storage} and {var_name_index} will contain 2400 // DescriptorArray and an index of the descriptor's name respectively. 2401 // If the {object} is slow or global then the control goes to {if_found_dict} 2402 // or {if_found_global} and the {var_meta_storage} and {var_name_index} will 2403 // contain a dictionary and an index of the key field of the found entry. 2404 // If property is not found or given lookup is not supported then 2405 // the control goes to {if_not_found} or {if_bailout} respectively. 2406 // 2407 // Note: this code does not check if the global dictionary points to deleted 2408 // entry! This has to be done by the caller. 2409 void TryLookupProperty(SloppyTNode<JSObject> object, SloppyTNode<Map> map, 2410 SloppyTNode<Int32T> instance_type, 2411 SloppyTNode<Name> unique_name, Label* if_found_fast, 2412 Label* if_found_dict, Label* if_found_global, 2413 TVariable<HeapObject>* var_meta_storage, 2414 TVariable<IntPtrT>* var_name_index, 2415 Label* if_not_found, Label* if_bailout); 2416 2417 // This is a building block for TryLookupProperty() above. Supports only 2418 // non-special fast and dictionary objects. 2419 void TryLookupPropertyInSimpleObject(TNode<JSObject> object, TNode<Map> map, 2420 TNode<Name> unique_name, 2421 Label* if_found_fast, 2422 Label* if_found_dict, 2423 TVariable<HeapObject>* var_meta_storage, 2424 TVariable<IntPtrT>* var_name_index, 2425 Label* if_not_found); 2426 2427 // This method jumps to if_found if the element is known to exist. To 2428 // if_absent if it's known to not exist. To if_not_found if the prototype 2429 // chain needs to be checked. And if_bailout if the lookup is unsupported. 2430 void TryLookupElement(Node* object, Node* map, 2431 SloppyTNode<Int32T> instance_type, 2432 SloppyTNode<IntPtrT> intptr_index, Label* if_found, 2433 Label* if_absent, Label* if_not_found, 2434 Label* if_bailout); 2435 2436 // This is a type of a lookup in holder generator function. In case of a 2437 // property lookup the {key} is guaranteed to be an unique name and in case of 2438 // element lookup the key is an Int32 index. 2439 typedef std::function<void(Node* receiver, Node* holder, Node* map, 2440 Node* instance_type, Node* key, Label* next_holder, 2441 Label* if_bailout)> 2442 LookupInHolder; 2443 2444 // For integer indexed exotic cases, check if the given string cannot be a 2445 // special index. If we are not sure that the given string is not a special 2446 // index with a simple check, return False. Note that "False" return value 2447 // does not mean that the name_string is a special index in the current 2448 // implementation. 2449 void BranchIfMaybeSpecialIndex(TNode<String> name_string, 2450 Label* if_maybe_special_index, 2451 Label* if_not_special_index); 2452 2453 // Generic property prototype chain lookup generator. 2454 // For properties it generates lookup using given {lookup_property_in_holder} 2455 // and for elements it uses {lookup_element_in_holder}. 2456 // Upon reaching the end of prototype chain the control goes to {if_end}. 2457 // If it can't handle the case {receiver}/{key} case then the control goes 2458 // to {if_bailout}. 2459 // If {if_proxy} is nullptr, proxies go to if_bailout. 2460 void TryPrototypeChainLookup(Node* receiver, Node* key, 2461 const LookupInHolder& lookup_property_in_holder, 2462 const LookupInHolder& lookup_element_in_holder, 2463 Label* if_end, Label* if_bailout, 2464 Label* if_proxy = nullptr); 2465 2466 // Instanceof helpers. 2467 // Returns true if {object} has {prototype} somewhere in it's prototype 2468 // chain, otherwise false is returned. Might cause arbitrary side effects 2469 // due to [[GetPrototypeOf]] invocations. 2470 Node* HasInPrototypeChain(Node* context, Node* object, Node* prototype); 2471 // ES6 section 7.3.19 OrdinaryHasInstance (C, O) 2472 Node* OrdinaryHasInstance(Node* context, Node* callable, Node* object); 2473 2474 // Load type feedback vector from the stub caller's frame. 2475 TNode<FeedbackVector> LoadFeedbackVectorForStub(); 2476 2477 // Load type feedback vector for the given closure. 2478 TNode<FeedbackVector> LoadFeedbackVector(SloppyTNode<JSFunction> closure, 2479 Label* if_undefined = nullptr); 2480 2481 // Update the type feedback vector. 2482 void UpdateFeedback(Node* feedback, Node* feedback_vector, Node* slot_id); 2483 2484 // Report that there was a feedback update, performing any tasks that should 2485 // be done after a feedback update. 2486 void ReportFeedbackUpdate(SloppyTNode<FeedbackVector> feedback_vector, 2487 SloppyTNode<IntPtrT> slot_id, const char* reason); 2488 2489 // Combine the new feedback with the existing_feedback. Do nothing if 2490 // existing_feedback is nullptr. 2491 void CombineFeedback(Variable* existing_feedback, int feedback); 2492 void CombineFeedback(Variable* existing_feedback, Node* feedback); 2493 2494 // Overwrite the existing feedback with new_feedback. Do nothing if 2495 // existing_feedback is nullptr. 2496 void OverwriteFeedback(Variable* existing_feedback, int new_feedback); 2497 2498 // Check if a property name might require protector invalidation when it is 2499 // used for a property store or deletion. 2500 void CheckForAssociatedProtector(Node* name, Label* if_protector); 2501 2502 TNode<Map> LoadReceiverMap(SloppyTNode<Object> receiver); 2503 2504 // Emits keyed sloppy arguments load. Returns either the loaded value. LoadKeyedSloppyArguments(Node * receiver,Node * key,Label * bailout)2505 Node* LoadKeyedSloppyArguments(Node* receiver, Node* key, Label* bailout) { 2506 return EmitKeyedSloppyArguments(receiver, key, nullptr, bailout); 2507 } 2508 2509 // Emits keyed sloppy arguments store. StoreKeyedSloppyArguments(Node * receiver,Node * key,Node * value,Label * bailout)2510 void StoreKeyedSloppyArguments(Node* receiver, Node* key, Node* value, 2511 Label* bailout) { 2512 DCHECK_NOT_NULL(value); 2513 EmitKeyedSloppyArguments(receiver, key, value, bailout); 2514 } 2515 2516 // Loads script context from the script context table. 2517 TNode<Context> LoadScriptContext(TNode<Context> context, 2518 TNode<IntPtrT> context_index); 2519 2520 Node* Int32ToUint8Clamped(Node* int32_value); 2521 Node* Float64ToUint8Clamped(Node* float64_value); 2522 2523 Node* PrepareValueForWriteToTypedArray(TNode<Object> input, 2524 ElementsKind elements_kind, 2525 TNode<Context> context); 2526 2527 // Store value to an elements array with given elements kind. 2528 void StoreElement(Node* elements, ElementsKind kind, Node* index, Node* value, 2529 ParameterMode mode); 2530 2531 void EmitBigTypedArrayElementStore(TNode<JSTypedArray> object, 2532 TNode<FixedTypedArrayBase> elements, 2533 TNode<IntPtrT> intptr_key, 2534 TNode<Object> value, 2535 TNode<Context> context, 2536 Label* opt_if_neutered); 2537 // Part of the above, refactored out to reuse in another place 2538 void EmitBigTypedArrayElementStore(TNode<FixedTypedArrayBase> elements, 2539 TNode<RawPtrT> backing_store, 2540 TNode<IntPtrT> offset, 2541 TNode<BigInt> bigint_value); 2542 2543 void EmitElementStore(Node* object, Node* key, Node* value, bool is_jsarray, 2544 ElementsKind elements_kind, 2545 KeyedAccessStoreMode store_mode, Label* bailout, 2546 Node* context); 2547 2548 Node* CheckForCapacityGrow(Node* object, Node* elements, ElementsKind kind, 2549 KeyedAccessStoreMode store_mode, Node* length, 2550 Node* key, ParameterMode mode, bool is_js_array, 2551 Label* bailout); 2552 2553 Node* CopyElementsOnWrite(Node* object, Node* elements, ElementsKind kind, 2554 Node* length, ParameterMode mode, Label* bailout); 2555 2556 void TransitionElementsKind(Node* object, Node* map, ElementsKind from_kind, 2557 ElementsKind to_kind, bool is_jsarray, 2558 Label* bailout); 2559 2560 void TrapAllocationMemento(Node* object, Label* memento_found); 2561 2562 TNode<IntPtrT> PageFromAddress(TNode<IntPtrT> address); 2563 2564 // Store a weak in-place reference into the FeedbackVector. 2565 TNode<MaybeObject> StoreWeakReferenceInFeedbackVector( 2566 SloppyTNode<FeedbackVector> feedback_vector, Node* slot, 2567 SloppyTNode<HeapObject> value, int additional_offset = 0, 2568 ParameterMode parameter_mode = INTPTR_PARAMETERS); 2569 2570 // Create a new AllocationSite and install it into a feedback vector. 2571 TNode<AllocationSite> CreateAllocationSiteInFeedbackVector( 2572 SloppyTNode<FeedbackVector> feedback_vector, TNode<Smi> slot); 2573 2574 // TODO(ishell, cbruni): Change to HasBoilerplate. 2575 TNode<BoolT> NotHasBoilerplate(TNode<Object> maybe_literal_site); 2576 TNode<Smi> LoadTransitionInfo(TNode<AllocationSite> allocation_site); 2577 TNode<JSObject> LoadBoilerplate(TNode<AllocationSite> allocation_site); 2578 TNode<Int32T> LoadElementsKind(TNode<AllocationSite> allocation_site); 2579 2580 enum class IndexAdvanceMode { kPre, kPost }; 2581 2582 typedef std::function<void(Node* index)> FastLoopBody; 2583 2584 Node* BuildFastLoop(const VariableList& var_list, Node* start_index, 2585 Node* end_index, const FastLoopBody& body, int increment, 2586 ParameterMode parameter_mode, 2587 IndexAdvanceMode advance_mode = IndexAdvanceMode::kPre); 2588 2589 Node* BuildFastLoop(Node* start_index, Node* end_index, 2590 const FastLoopBody& body, int increment, 2591 ParameterMode parameter_mode, 2592 IndexAdvanceMode advance_mode = IndexAdvanceMode::kPre) { 2593 return BuildFastLoop(VariableList(0, zone()), start_index, end_index, body, 2594 increment, parameter_mode, advance_mode); 2595 } 2596 2597 enum class ForEachDirection { kForward, kReverse }; 2598 2599 typedef std::function<void(Node* fixed_array, Node* offset)> 2600 FastFixedArrayForEachBody; 2601 2602 void BuildFastFixedArrayForEach( 2603 const CodeStubAssembler::VariableList& vars, Node* fixed_array, 2604 ElementsKind kind, Node* first_element_inclusive, 2605 Node* last_element_exclusive, const FastFixedArrayForEachBody& body, 2606 ParameterMode mode = INTPTR_PARAMETERS, 2607 ForEachDirection direction = ForEachDirection::kReverse); 2608 2609 void BuildFastFixedArrayForEach( 2610 Node* fixed_array, ElementsKind kind, Node* first_element_inclusive, 2611 Node* last_element_exclusive, const FastFixedArrayForEachBody& body, 2612 ParameterMode mode = INTPTR_PARAMETERS, 2613 ForEachDirection direction = ForEachDirection::kReverse) { 2614 CodeStubAssembler::VariableList list(0, zone()); 2615 BuildFastFixedArrayForEach(list, fixed_array, kind, first_element_inclusive, 2616 last_element_exclusive, body, mode, direction); 2617 } 2618 GetArrayAllocationSize(Node * element_count,ElementsKind kind,ParameterMode mode,int header_size)2619 TNode<IntPtrT> GetArrayAllocationSize(Node* element_count, ElementsKind kind, 2620 ParameterMode mode, int header_size) { 2621 return ElementOffsetFromIndex(element_count, kind, mode, header_size); 2622 } 2623 GetFixedArrayAllocationSize(Node * element_count,ElementsKind kind,ParameterMode mode)2624 TNode<IntPtrT> GetFixedArrayAllocationSize(Node* element_count, 2625 ElementsKind kind, 2626 ParameterMode mode) { 2627 return GetArrayAllocationSize(element_count, kind, mode, 2628 FixedArray::kHeaderSize); 2629 } 2630 GetPropertyArrayAllocationSize(Node * element_count,ParameterMode mode)2631 TNode<IntPtrT> GetPropertyArrayAllocationSize(Node* element_count, 2632 ParameterMode mode) { 2633 return GetArrayAllocationSize(element_count, PACKED_ELEMENTS, mode, 2634 PropertyArray::kHeaderSize); 2635 } 2636 2637 void GotoIfFixedArraySizeDoesntFitInNewSpace(Node* element_count, 2638 Label* doesnt_fit, int base_size, 2639 ParameterMode mode); 2640 2641 void InitializeFieldsWithRoot(Node* object, Node* start_offset, 2642 Node* end_offset, Heap::RootListIndex root); 2643 2644 Node* RelationalComparison(Operation op, Node* left, Node* right, 2645 Node* context, 2646 Variable* var_type_feedback = nullptr); 2647 2648 void BranchIfNumberRelationalComparison(Operation op, Node* left, Node* right, 2649 Label* if_true, Label* if_false); 2650 BranchIfNumberLessThan(Node * left,Node * right,Label * if_true,Label * if_false)2651 void BranchIfNumberLessThan(Node* left, Node* right, Label* if_true, 2652 Label* if_false) { 2653 BranchIfNumberRelationalComparison(Operation::kLessThan, left, right, 2654 if_true, if_false); 2655 } 2656 BranchIfNumberLessThanOrEqual(Node * left,Node * right,Label * if_true,Label * if_false)2657 void BranchIfNumberLessThanOrEqual(Node* left, Node* right, Label* if_true, 2658 Label* if_false) { 2659 BranchIfNumberRelationalComparison(Operation::kLessThanOrEqual, left, right, 2660 if_true, if_false); 2661 } 2662 BranchIfNumberGreaterThan(Node * left,Node * right,Label * if_true,Label * if_false)2663 void BranchIfNumberGreaterThan(Node* left, Node* right, Label* if_true, 2664 Label* if_false) { 2665 BranchIfNumberRelationalComparison(Operation::kGreaterThan, left, right, 2666 if_true, if_false); 2667 } 2668 BranchIfNumberGreaterThanOrEqual(Node * left,Node * right,Label * if_true,Label * if_false)2669 void BranchIfNumberGreaterThanOrEqual(Node* left, Node* right, Label* if_true, 2670 Label* if_false) { 2671 BranchIfNumberRelationalComparison(Operation::kGreaterThanOrEqual, left, 2672 right, if_true, if_false); 2673 } 2674 BranchIfAccessorPair(Node * value,Label * if_accessor_pair,Label * if_not_accessor_pair)2675 void BranchIfAccessorPair(Node* value, Label* if_accessor_pair, 2676 Label* if_not_accessor_pair) { 2677 GotoIf(TaggedIsSmi(value), if_not_accessor_pair); 2678 Branch(IsAccessorPair(value), if_accessor_pair, if_not_accessor_pair); 2679 } 2680 2681 void GotoIfNumberGreaterThanOrEqual(Node* left, Node* right, Label* if_false); 2682 2683 Node* Equal(Node* lhs, Node* rhs, Node* context, 2684 Variable* var_type_feedback = nullptr); 2685 2686 Node* StrictEqual(Node* lhs, Node* rhs, 2687 Variable* var_type_feedback = nullptr); 2688 2689 // ECMA#sec-samevalue 2690 // Similar to StrictEqual except that NaNs are treated as equal and minus zero 2691 // differs from positive zero. 2692 void BranchIfSameValue(Node* lhs, Node* rhs, Label* if_true, Label* if_false); 2693 2694 enum HasPropertyLookupMode { kHasProperty, kForInHasProperty }; 2695 2696 TNode<Oddball> HasProperty(SloppyTNode<Context> context, 2697 SloppyTNode<Object> object, 2698 SloppyTNode<Object> key, 2699 HasPropertyLookupMode mode); 2700 2701 Node* Typeof(Node* value); 2702 2703 TNode<Object> GetSuperConstructor(SloppyTNode<Context> context, 2704 SloppyTNode<JSFunction> active_function); 2705 2706 TNode<Object> SpeciesConstructor(SloppyTNode<Context> context, 2707 SloppyTNode<Object> object, 2708 SloppyTNode<Object> default_constructor); 2709 2710 Node* InstanceOf(Node* object, Node* callable, Node* context); 2711 2712 // Debug helpers 2713 Node* IsDebugActive(); 2714 2715 TNode<BoolT> IsRuntimeCallStatsEnabled(); 2716 2717 // TypedArray/ArrayBuffer helpers 2718 Node* IsDetachedBuffer(Node* buffer); 2719 void ThrowIfArrayBufferIsDetached(SloppyTNode<Context> context, 2720 TNode<JSArrayBuffer> array_buffer, 2721 const char* method_name); 2722 void ThrowIfArrayBufferViewBufferIsDetached( 2723 SloppyTNode<Context> context, TNode<JSArrayBufferView> array_buffer_view, 2724 const char* method_name); 2725 TNode<JSArrayBuffer> LoadArrayBufferViewBuffer( 2726 TNode<JSArrayBufferView> array_buffer_view); 2727 TNode<RawPtrT> LoadArrayBufferBackingStore(TNode<JSArrayBuffer> array_buffer); 2728 2729 TNode<IntPtrT> ElementOffsetFromIndex(Node* index, ElementsKind kind, 2730 ParameterMode mode, int base_size = 0); 2731 2732 // Check that a field offset is within the bounds of the an object. 2733 TNode<BoolT> IsOffsetInBounds(SloppyTNode<IntPtrT> offset, 2734 SloppyTNode<IntPtrT> length, int header_size, 2735 ElementsKind kind = HOLEY_ELEMENTS); 2736 2737 // Load a builtin's code from the builtin array in the isolate. 2738 TNode<Code> LoadBuiltin(TNode<Smi> builtin_id); 2739 2740 // Figure out the SFI's code object using its data field. 2741 // If |if_compile_lazy| is provided then the execution will go to the given 2742 // label in case of an CompileLazy code object. 2743 TNode<Code> GetSharedFunctionInfoCode( 2744 SloppyTNode<SharedFunctionInfo> shared_info, 2745 Label* if_compile_lazy = nullptr); 2746 2747 Node* AllocateFunctionWithMapAndContext(Node* map, Node* shared_info, 2748 Node* context); 2749 2750 // Promise helpers 2751 Node* IsPromiseHookEnabled(); 2752 Node* HasAsyncEventDelegate(); 2753 Node* IsPromiseHookEnabledOrHasAsyncEventDelegate(); 2754 2755 // Helpers for StackFrame markers. 2756 Node* MarkerIsFrameType(Node* marker_or_function, 2757 StackFrame::Type frame_type); 2758 Node* MarkerIsNotFrameType(Node* marker_or_function, 2759 StackFrame::Type frame_type); 2760 2761 // for..in helpers 2762 void CheckPrototypeEnumCache(Node* receiver, Node* receiver_map, 2763 Label* if_fast, Label* if_slow); 2764 Node* CheckEnumCache(Node* receiver, Label* if_empty, Label* if_runtime); 2765 2766 TNode<IntPtrT> GetArgumentsLength(CodeStubArguments* args); 2767 TNode<Object> GetArgumentValue(CodeStubArguments* args, TNode<IntPtrT> index); 2768 2769 // Support for printf-style debugging 2770 void Print(const char* s); 2771 void Print(const char* prefix, Node* tagged_value); Print(SloppyTNode<Object> tagged_value)2772 inline void Print(SloppyTNode<Object> tagged_value) { 2773 return Print(nullptr, tagged_value); 2774 } Print(TNode<MaybeObject> tagged_value)2775 inline void Print(TNode<MaybeObject> tagged_value) { 2776 return Print(nullptr, tagged_value); 2777 } 2778 2779 template <class... TArgs> MakeTypeError(MessageTemplate::Template message,Node * context,TArgs...args)2780 Node* MakeTypeError(MessageTemplate::Template message, Node* context, 2781 TArgs... args) { 2782 STATIC_ASSERT(sizeof...(TArgs) <= 3); 2783 Node* const make_type_error = LoadContextElement( 2784 LoadNativeContext(context), Context::MAKE_TYPE_ERROR_INDEX); 2785 return CallJS(CodeFactory::Call(isolate()), context, make_type_error, 2786 UndefinedConstant(), SmiConstant(message), args...); 2787 } 2788 Abort(AbortReason reason)2789 void Abort(AbortReason reason) { 2790 CallRuntime(Runtime::kAbort, NoContextConstant(), SmiConstant(reason)); 2791 Unreachable(); 2792 } 2793 ConstexprBoolNot(bool value)2794 bool ConstexprBoolNot(bool value) { return !value; } 2795 ConstexprInt31Equal(int31_t a,int31_t b)2796 bool ConstexprInt31Equal(int31_t a, int31_t b) { return a == b; } 2797 2798 void PerformStackCheck(TNode<Context> context); 2799 2800 protected: 2801 // Implements DescriptorArray::Search(). 2802 void DescriptorLookup(SloppyTNode<Name> unique_name, 2803 SloppyTNode<DescriptorArray> descriptors, 2804 SloppyTNode<Uint32T> bitfield3, Label* if_found, 2805 TVariable<IntPtrT>* var_name_index, 2806 Label* if_not_found); 2807 2808 // Implements TransitionArray::SearchName() - searches for first transition 2809 // entry with given name (note that there could be multiple entries with 2810 // the same name). 2811 void TransitionLookup(SloppyTNode<Name> unique_name, 2812 SloppyTNode<TransitionArray> transitions, 2813 Label* if_found, TVariable<IntPtrT>* var_name_index, 2814 Label* if_not_found); 2815 2816 // Implements generic search procedure like i::Search<Array>(). 2817 template <typename Array> 2818 void Lookup(TNode<Name> unique_name, TNode<Array> array, 2819 TNode<Uint32T> number_of_valid_entries, Label* if_found, 2820 TVariable<IntPtrT>* var_name_index, Label* if_not_found); 2821 2822 // Implements generic linear search procedure like i::LinearSearch<Array>(). 2823 template <typename Array> 2824 void LookupLinear(TNode<Name> unique_name, TNode<Array> array, 2825 TNode<Uint32T> number_of_valid_entries, Label* if_found, 2826 TVariable<IntPtrT>* var_name_index, Label* if_not_found); 2827 2828 // Implements generic binary search procedure like i::BinarySearch<Array>(). 2829 template <typename Array> 2830 void LookupBinary(TNode<Name> unique_name, TNode<Array> array, 2831 TNode<Uint32T> number_of_valid_entries, Label* if_found, 2832 TVariable<IntPtrT>* var_name_index, Label* if_not_found); 2833 2834 // Converts [Descriptor/Transition]Array entry number to a fixed array index. 2835 template <typename Array> 2836 TNode<IntPtrT> EntryIndexToIndex(TNode<Uint32T> entry_index); 2837 2838 // Implements [Descriptor/Transition]Array::ToKeyIndex. 2839 template <typename Array> 2840 TNode<IntPtrT> ToKeyIndex(TNode<Uint32T> entry_index); 2841 2842 // Implements [Descriptor/Transition]Array::GetKey. 2843 template <typename Array> 2844 TNode<Name> GetKey(TNode<Array> array, TNode<Uint32T> entry_index); 2845 2846 // Implements DescriptorArray::GetDetails. 2847 TNode<Uint32T> DescriptorArrayGetDetails(TNode<DescriptorArray> descriptors, 2848 TNode<Uint32T> descriptor_number); 2849 2850 typedef std::function<void(TNode<UintPtrT> descriptor_key_index)> 2851 ForEachDescriptorBodyFunction; 2852 2853 void DescriptorArrayForEach(VariableList& variable_list, 2854 TNode<Uint32T> start_descriptor, 2855 TNode<Uint32T> end_descriptor, 2856 const ForEachDescriptorBodyFunction& body); 2857 2858 TNode<Object> CallGetterIfAccessor(Node* value, Node* details, Node* context, 2859 Node* receiver, Label* if_bailout, 2860 GetOwnPropertyMode mode = kCallJSGetter); 2861 2862 TNode<IntPtrT> TryToIntptr(Node* key, Label* miss); 2863 2864 void BranchIfPrototypesHaveNoElements(Node* receiver_map, 2865 Label* definitely_no_elements, 2866 Label* possibly_elements); 2867 2868 void InitializeFunctionContext(Node* native_context, Node* context, 2869 int slots); 2870 2871 private: 2872 friend class CodeStubArguments; 2873 2874 void HandleBreakOnNode(); 2875 2876 Node* AllocateRawDoubleAligned(Node* size_in_bytes, AllocationFlags flags, 2877 Node* top_address, Node* limit_address); 2878 Node* AllocateRawUnaligned(Node* size_in_bytes, AllocationFlags flags, 2879 Node* top_adddress, Node* limit_address); 2880 Node* AllocateRaw(Node* size_in_bytes, AllocationFlags flags, 2881 Node* top_address, Node* limit_address); 2882 // Allocate and return a JSArray of given total size in bytes with header 2883 // fields initialized. 2884 Node* AllocateUninitializedJSArray(Node* array_map, Node* length, 2885 Node* allocation_site, 2886 Node* size_in_bytes); 2887 2888 TNode<BoolT> IsValidSmi(TNode<Smi> smi); 2889 Node* SmiShiftBitsConstant(); 2890 2891 // Emits keyed sloppy arguments load if the |value| is nullptr or store 2892 // otherwise. Returns either the loaded value or |value|. 2893 Node* EmitKeyedSloppyArguments(Node* receiver, Node* key, Node* value, 2894 Label* bailout); 2895 2896 TNode<String> AllocateSlicedString(Heap::RootListIndex map_root_index, 2897 TNode<Smi> length, TNode<String> parent, 2898 TNode<Smi> offset); 2899 2900 TNode<String> AllocateConsString(Heap::RootListIndex map_root_index, 2901 TNode<Smi> length, TNode<String> first, 2902 TNode<String> second, AllocationFlags flags); 2903 2904 // Allocate a MutableHeapNumber without initializing its value. 2905 TNode<MutableHeapNumber> AllocateMutableHeapNumber(); 2906 2907 Node* SelectImpl(TNode<BoolT> condition, const NodeGenerator& true_body, 2908 const NodeGenerator& false_body, MachineRepresentation rep); 2909 2910 // Implements [Descriptor/Transition]Array::number_of_entries. 2911 template <typename Array> 2912 TNode<Uint32T> NumberOfEntries(TNode<Array> array); 2913 2914 // Implements [Descriptor/Transition]Array::GetSortedKeyIndex. 2915 template <typename Array> 2916 TNode<Uint32T> GetSortedKeyIndex(TNode<Array> descriptors, 2917 TNode<Uint32T> entry_index); 2918 2919 TNode<Smi> CollectFeedbackForString(SloppyTNode<Int32T> instance_type); 2920 void GenerateEqual_Same(Node* value, Label* if_equal, Label* if_notequal, 2921 Variable* var_type_feedback = nullptr); 2922 TNode<String> AllocAndCopyStringCharacters(Node* from, 2923 Node* from_instance_type, 2924 TNode<IntPtrT> from_index, 2925 TNode<Smi> character_count); 2926 2927 static const int kElementLoopUnrollThreshold = 8; 2928 2929 // {convert_bigint} is only meaningful when {mode} == kToNumber. 2930 Node* NonNumberToNumberOrNumeric( 2931 Node* context, Node* input, Object::Conversion mode, 2932 BigIntHandling bigint_handling = BigIntHandling::kThrow); 2933 2934 void TaggedToNumeric(Node* context, Node* value, Label* done, 2935 Variable* var_numeric, Variable* var_feedback); 2936 2937 template <Object::Conversion conversion> 2938 void TaggedToWord32OrBigIntImpl(Node* context, Node* value, Label* if_number, 2939 Variable* var_word32, 2940 Label* if_bigint = nullptr, 2941 Variable* var_bigint = nullptr, 2942 Variable* var_feedback = nullptr); 2943 }; 2944 2945 class CodeStubArguments { 2946 public: 2947 typedef compiler::Node Node; 2948 template <class T> 2949 using TNode = compiler::TNode<T>; 2950 template <class T> 2951 using SloppyTNode = compiler::SloppyTNode<T>; 2952 enum ReceiverMode { kHasReceiver, kNoReceiver }; 2953 2954 // |argc| is an intptr value which specifies the number of arguments passed 2955 // to the builtin excluding the receiver. The arguments will include a 2956 // receiver iff |receiver_mode| is kHasReceiver. 2957 CodeStubArguments(CodeStubAssembler* assembler, Node* argc, 2958 ReceiverMode receiver_mode = ReceiverMode::kHasReceiver) CodeStubArguments(assembler,argc,nullptr,CodeStubAssembler::INTPTR_PARAMETERS,receiver_mode)2959 : CodeStubArguments(assembler, argc, nullptr, 2960 CodeStubAssembler::INTPTR_PARAMETERS, receiver_mode) { 2961 } 2962 2963 // |argc| is either a smi or intptr depending on |param_mode|. The arguments 2964 // include a receiver iff |receiver_mode| is kHasReceiver. 2965 CodeStubArguments(CodeStubAssembler* assembler, Node* argc, Node* fp, 2966 CodeStubAssembler::ParameterMode param_mode, 2967 ReceiverMode receiver_mode = ReceiverMode::kHasReceiver); 2968 2969 TNode<Object> GetReceiver() const; 2970 // Replaces receiver argument on the expression stack. Should be used only 2971 // for manipulating arguments in trampoline builtins before tail calling 2972 // further with passing all the JS arguments as is. 2973 void SetReceiver(TNode<Object> object) const; 2974 2975 TNode<RawPtr<Object>> AtIndexPtr( 2976 Node* index, CodeStubAssembler::ParameterMode mode = 2977 CodeStubAssembler::INTPTR_PARAMETERS) const; 2978 2979 // |index| is zero-based and does not include the receiver 2980 TNode<Object> AtIndex(Node* index, 2981 CodeStubAssembler::ParameterMode mode = 2982 CodeStubAssembler::INTPTR_PARAMETERS) const; 2983 2984 TNode<Object> AtIndex(int index) const; 2985 GetOptionalArgumentValue(int index)2986 TNode<Object> GetOptionalArgumentValue(int index) { 2987 return GetOptionalArgumentValue(index, assembler_->UndefinedConstant()); 2988 } 2989 TNode<Object> GetOptionalArgumentValue(int index, 2990 TNode<Object> default_value); 2991 GetLength(CodeStubAssembler::ParameterMode mode)2992 Node* GetLength(CodeStubAssembler::ParameterMode mode) const { 2993 DCHECK_EQ(mode, argc_mode_); 2994 return argc_; 2995 } 2996 GetOptionalArgumentValue(TNode<IntPtrT> index)2997 TNode<Object> GetOptionalArgumentValue(TNode<IntPtrT> index) { 2998 return GetOptionalArgumentValue(index, assembler_->UndefinedConstant()); 2999 } 3000 TNode<Object> GetOptionalArgumentValue(TNode<IntPtrT> index, 3001 TNode<Object> default_value); GetLength()3002 TNode<IntPtrT> GetLength() const { 3003 DCHECK_EQ(argc_mode_, CodeStubAssembler::INTPTR_PARAMETERS); 3004 return assembler_->UncheckedCast<IntPtrT>(argc_); 3005 } 3006 3007 typedef std::function<void(Node* arg)> ForEachBodyFunction; 3008 3009 // Iteration doesn't include the receiver. |first| and |last| are zero-based. 3010 void ForEach(const ForEachBodyFunction& body, Node* first = nullptr, 3011 Node* last = nullptr, 3012 CodeStubAssembler::ParameterMode mode = 3013 CodeStubAssembler::INTPTR_PARAMETERS) { 3014 CodeStubAssembler::VariableList list(0, assembler_->zone()); 3015 ForEach(list, body, first, last); 3016 } 3017 3018 // Iteration doesn't include the receiver. |first| and |last| are zero-based. 3019 void ForEach(const CodeStubAssembler::VariableList& vars, 3020 const ForEachBodyFunction& body, Node* first = nullptr, 3021 Node* last = nullptr, 3022 CodeStubAssembler::ParameterMode mode = 3023 CodeStubAssembler::INTPTR_PARAMETERS); 3024 3025 void PopAndReturn(Node* value); 3026 3027 private: 3028 Node* GetArguments(); 3029 3030 CodeStubAssembler* assembler_; 3031 CodeStubAssembler::ParameterMode argc_mode_; 3032 ReceiverMode receiver_mode_; 3033 Node* argc_; 3034 TNode<RawPtr<Object>> arguments_; 3035 Node* fp_; 3036 }; 3037 3038 class ToDirectStringAssembler : public CodeStubAssembler { 3039 private: 3040 enum StringPointerKind { PTR_TO_DATA, PTR_TO_STRING }; 3041 3042 public: 3043 enum Flag { 3044 kDontUnpackSlicedStrings = 1 << 0, 3045 }; 3046 typedef base::Flags<Flag> Flags; 3047 3048 ToDirectStringAssembler(compiler::CodeAssemblerState* state, Node* string, 3049 Flags flags = Flags()); 3050 3051 // Converts flat cons, thin, and sliced strings and returns the direct 3052 // string. The result can be either a sequential or external string. 3053 // Jumps to if_bailout if the string if the string is indirect and cannot 3054 // be unpacked. 3055 TNode<String> TryToDirect(Label* if_bailout); 3056 3057 // Returns a pointer to the beginning of the string data. 3058 // Jumps to if_bailout if the external string cannot be unpacked. PointerToData(Label * if_bailout)3059 TNode<RawPtrT> PointerToData(Label* if_bailout) { 3060 return TryToSequential(PTR_TO_DATA, if_bailout); 3061 } 3062 3063 // Returns a pointer that, offset-wise, looks like a String. 3064 // Jumps to if_bailout if the external string cannot be unpacked. PointerToString(Label * if_bailout)3065 TNode<RawPtrT> PointerToString(Label* if_bailout) { 3066 return TryToSequential(PTR_TO_STRING, if_bailout); 3067 } 3068 string()3069 Node* string() { return var_string_.value(); } instance_type()3070 Node* instance_type() { return var_instance_type_.value(); } offset()3071 TNode<IntPtrT> offset() { 3072 return UncheckedCast<IntPtrT>(var_offset_.value()); 3073 } is_external()3074 Node* is_external() { return var_is_external_.value(); } 3075 3076 private: 3077 TNode<RawPtrT> TryToSequential(StringPointerKind ptr_kind, Label* if_bailout); 3078 3079 Variable var_string_; 3080 Variable var_instance_type_; 3081 Variable var_offset_; 3082 Variable var_is_external_; 3083 3084 const Flags flags_; 3085 }; 3086 3087 3088 DEFINE_OPERATORS_FOR_FLAGS(CodeStubAssembler::AllocationFlags); 3089 3090 } // namespace internal 3091 } // namespace v8 3092 #endif // V8_CODE_STUB_ASSEMBLER_H_ 3093