Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 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 "src/compiler/code-assembler.h" |
| 9 | #include "src/objects.h" |
| 10 | |
| 11 | namespace v8 { |
| 12 | namespace internal { |
| 13 | |
| 14 | class CallInterfaceDescriptor; |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 15 | class StatsCounter; |
| 16 | class StubCache; |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 17 | |
| 18 | // Provides JavaScript-specific "macro-assembler" functionality on top of the |
| 19 | // CodeAssembler. By factoring the JavaScript-isms out of the CodeAssembler, |
| 20 | // it's possible to add JavaScript-specific useful CodeAssembler "macros" |
| 21 | // without modifying files in the compiler directory (and requiring a review |
| 22 | // from a compiler directory OWNER). |
| 23 | class CodeStubAssembler : public compiler::CodeAssembler { |
| 24 | public: |
| 25 | // Create with CallStub linkage. |
| 26 | // |result_size| specifies the number of results returned by the stub. |
| 27 | // TODO(rmcilroy): move result_size to the CallInterfaceDescriptor. |
| 28 | CodeStubAssembler(Isolate* isolate, Zone* zone, |
| 29 | const CallInterfaceDescriptor& descriptor, |
| 30 | Code::Flags flags, const char* name, |
| 31 | size_t result_size = 1); |
| 32 | |
| 33 | // Create with JSCall linkage. |
| 34 | CodeStubAssembler(Isolate* isolate, Zone* zone, int parameter_count, |
| 35 | Code::Flags flags, const char* name); |
| 36 | |
| 37 | enum ParameterMode { INTEGER_PARAMETERS, SMI_PARAMETERS }; |
| 38 | |
| 39 | compiler::Node* BooleanMapConstant(); |
| 40 | compiler::Node* EmptyStringConstant(); |
| 41 | compiler::Node* HeapNumberMapConstant(); |
| 42 | compiler::Node* NoContextConstant(); |
| 43 | compiler::Node* NullConstant(); |
| 44 | compiler::Node* UndefinedConstant(); |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 45 | compiler::Node* TheHoleConstant(); |
| 46 | compiler::Node* HashSeed(); |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 47 | compiler::Node* StaleRegisterConstant(); |
| 48 | |
| 49 | // Float64 operations. |
| 50 | compiler::Node* Float64Ceil(compiler::Node* x); |
| 51 | compiler::Node* Float64Floor(compiler::Node* x); |
| 52 | compiler::Node* Float64Round(compiler::Node* x); |
| 53 | compiler::Node* Float64Trunc(compiler::Node* x); |
| 54 | |
| 55 | // Tag a Word as a Smi value. |
| 56 | compiler::Node* SmiTag(compiler::Node* value); |
| 57 | // Untag a Smi value as a Word. |
| 58 | compiler::Node* SmiUntag(compiler::Node* value); |
| 59 | |
| 60 | // Smi conversions. |
| 61 | compiler::Node* SmiToFloat64(compiler::Node* value); |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 62 | compiler::Node* SmiFromWord(compiler::Node* value) { return SmiTag(value); } |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 63 | compiler::Node* SmiFromWord32(compiler::Node* value); |
| 64 | compiler::Node* SmiToWord(compiler::Node* value) { return SmiUntag(value); } |
| 65 | compiler::Node* SmiToWord32(compiler::Node* value); |
| 66 | |
| 67 | // Smi operations. |
| 68 | compiler::Node* SmiAdd(compiler::Node* a, compiler::Node* b); |
| 69 | compiler::Node* SmiAddWithOverflow(compiler::Node* a, compiler::Node* b); |
| 70 | compiler::Node* SmiSub(compiler::Node* a, compiler::Node* b); |
| 71 | compiler::Node* SmiSubWithOverflow(compiler::Node* a, compiler::Node* b); |
| 72 | compiler::Node* SmiEqual(compiler::Node* a, compiler::Node* b); |
| 73 | compiler::Node* SmiAboveOrEqual(compiler::Node* a, compiler::Node* b); |
| 74 | compiler::Node* SmiLessThan(compiler::Node* a, compiler::Node* b); |
| 75 | compiler::Node* SmiLessThanOrEqual(compiler::Node* a, compiler::Node* b); |
| 76 | compiler::Node* SmiMin(compiler::Node* a, compiler::Node* b); |
| 77 | |
| 78 | // Allocate an object of the given size. |
| 79 | compiler::Node* Allocate(compiler::Node* size, AllocationFlags flags = kNone); |
| 80 | compiler::Node* Allocate(int size, AllocationFlags flags = kNone); |
| 81 | compiler::Node* InnerAllocate(compiler::Node* previous, int offset); |
| 82 | compiler::Node* InnerAllocate(compiler::Node* previous, |
| 83 | compiler::Node* offset); |
| 84 | |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 85 | void Assert(compiler::Node* condition); |
| 86 | |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 87 | // Check a value for smi-ness |
| 88 | compiler::Node* WordIsSmi(compiler::Node* a); |
| 89 | // Check that the value is a positive smi. |
| 90 | compiler::Node* WordIsPositiveSmi(compiler::Node* a); |
| 91 | |
| 92 | void BranchIfSmiLessThan(compiler::Node* a, compiler::Node* b, Label* if_true, |
| 93 | Label* if_false) { |
| 94 | BranchIf(SmiLessThan(a, b), if_true, if_false); |
| 95 | } |
| 96 | |
| 97 | void BranchIfSmiLessThanOrEqual(compiler::Node* a, compiler::Node* b, |
| 98 | Label* if_true, Label* if_false) { |
| 99 | BranchIf(SmiLessThanOrEqual(a, b), if_true, if_false); |
| 100 | } |
| 101 | |
| 102 | void BranchIfFloat64IsNaN(compiler::Node* value, Label* if_true, |
| 103 | Label* if_false) { |
| 104 | BranchIfFloat64Equal(value, value, if_false, if_true); |
| 105 | } |
| 106 | |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 107 | // Load value from current frame by given offset in bytes. |
| 108 | compiler::Node* LoadFromFrame(int offset, |
| 109 | MachineType rep = MachineType::AnyTagged()); |
| 110 | // Load value from current parent frame by given offset in bytes. |
| 111 | compiler::Node* LoadFromParentFrame( |
| 112 | int offset, MachineType rep = MachineType::AnyTagged()); |
| 113 | |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 114 | // Load an object pointer from a buffer that isn't in the heap. |
| 115 | compiler::Node* LoadBufferObject(compiler::Node* buffer, int offset, |
| 116 | MachineType rep = MachineType::AnyTagged()); |
| 117 | // Load a field from an object on the heap. |
| 118 | compiler::Node* LoadObjectField(compiler::Node* object, int offset, |
| 119 | MachineType rep = MachineType::AnyTagged()); |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 120 | compiler::Node* LoadObjectField(compiler::Node* object, |
| 121 | compiler::Node* offset, |
| 122 | MachineType rep = MachineType::AnyTagged()); |
| 123 | |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 124 | // Load the floating point value of a HeapNumber. |
| 125 | compiler::Node* LoadHeapNumberValue(compiler::Node* object); |
| 126 | // Load the Map of an HeapObject. |
| 127 | compiler::Node* LoadMap(compiler::Node* object); |
| 128 | // Load the instance type of an HeapObject. |
| 129 | compiler::Node* LoadInstanceType(compiler::Node* object); |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 130 | // Checks that given heap object has given instance type. |
| 131 | void AssertInstanceType(compiler::Node* object, InstanceType instance_type); |
| 132 | // Load the properties backing store of a JSObject. |
| 133 | compiler::Node* LoadProperties(compiler::Node* object); |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 134 | // Load the elements backing store of a JSObject. |
| 135 | compiler::Node* LoadElements(compiler::Node* object); |
| 136 | // Load the length of a fixed array base instance. |
| 137 | compiler::Node* LoadFixedArrayBaseLength(compiler::Node* array); |
| 138 | // Load the bit field of a Map. |
| 139 | compiler::Node* LoadMapBitField(compiler::Node* map); |
| 140 | // Load bit field 2 of a map. |
| 141 | compiler::Node* LoadMapBitField2(compiler::Node* map); |
| 142 | // Load bit field 3 of a map. |
| 143 | compiler::Node* LoadMapBitField3(compiler::Node* map); |
| 144 | // Load the instance type of a map. |
| 145 | compiler::Node* LoadMapInstanceType(compiler::Node* map); |
| 146 | // Load the instance descriptors of a map. |
| 147 | compiler::Node* LoadMapDescriptors(compiler::Node* map); |
| 148 | // Load the prototype of a map. |
| 149 | compiler::Node* LoadMapPrototype(compiler::Node* map); |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 150 | // Load the instance size of a Map. |
| 151 | compiler::Node* LoadMapInstanceSize(compiler::Node* map); |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 152 | // Load the inobject properties count of a Map (valid only for JSObjects). |
| 153 | compiler::Node* LoadMapInobjectProperties(compiler::Node* map); |
| 154 | |
| 155 | // Load the hash field of a name. |
| 156 | compiler::Node* LoadNameHashField(compiler::Node* name); |
| 157 | // Load the hash value of a name. If {if_hash_not_computed} label |
| 158 | // is specified then it also checks if hash is actually computed. |
| 159 | compiler::Node* LoadNameHash(compiler::Node* name, |
| 160 | Label* if_hash_not_computed = nullptr); |
| 161 | |
| 162 | // Load length field of a String object. |
| 163 | compiler::Node* LoadStringLength(compiler::Node* object); |
| 164 | // Load value field of a JSValue object. |
| 165 | compiler::Node* LoadJSValueValue(compiler::Node* object); |
| 166 | // Load value field of a WeakCell object. |
| 167 | compiler::Node* LoadWeakCellValue(compiler::Node* weak_cell, |
| 168 | Label* if_cleared = nullptr); |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 169 | |
| 170 | compiler::Node* AllocateUninitializedFixedArray(compiler::Node* length); |
| 171 | |
| 172 | // Load an array element from a FixedArray. |
| 173 | compiler::Node* LoadFixedArrayElement( |
| 174 | compiler::Node* object, compiler::Node* int32_index, |
| 175 | int additional_offset = 0, |
| 176 | ParameterMode parameter_mode = INTEGER_PARAMETERS); |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 177 | // Load an array element from a FixedDoubleArray. |
| 178 | compiler::Node* LoadFixedDoubleArrayElement( |
| 179 | compiler::Node* object, compiler::Node* int32_index, |
| 180 | MachineType machine_type, int additional_offset = 0, |
| 181 | ParameterMode parameter_mode = INTEGER_PARAMETERS); |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 182 | |
| 183 | // Context manipulation |
| 184 | compiler::Node* LoadNativeContext(compiler::Node* context); |
| 185 | |
| 186 | compiler::Node* LoadJSArrayElementsMap(ElementsKind kind, |
| 187 | compiler::Node* native_context); |
| 188 | |
| 189 | // Store the floating point value of a HeapNumber. |
| 190 | compiler::Node* StoreHeapNumberValue(compiler::Node* object, |
| 191 | compiler::Node* value); |
| 192 | // Store a field to an object on the heap. |
| 193 | compiler::Node* StoreObjectField( |
| 194 | compiler::Node* object, int offset, compiler::Node* value); |
| 195 | compiler::Node* StoreObjectFieldNoWriteBarrier( |
| 196 | compiler::Node* object, int offset, compiler::Node* value, |
| 197 | MachineRepresentation rep = MachineRepresentation::kTagged); |
| 198 | // Store the Map of an HeapObject. |
| 199 | compiler::Node* StoreMapNoWriteBarrier(compiler::Node* object, |
| 200 | compiler::Node* map); |
| 201 | // Store an array element to a FixedArray. |
| 202 | compiler::Node* StoreFixedArrayElement( |
| 203 | compiler::Node* object, compiler::Node* index, compiler::Node* value, |
| 204 | WriteBarrierMode barrier_mode = UPDATE_WRITE_BARRIER, |
| 205 | ParameterMode parameter_mode = INTEGER_PARAMETERS); |
| 206 | |
| 207 | compiler::Node* StoreFixedDoubleArrayElement( |
| 208 | compiler::Node* object, compiler::Node* index, compiler::Node* value, |
| 209 | ParameterMode parameter_mode = INTEGER_PARAMETERS); |
| 210 | |
| 211 | // Allocate a HeapNumber without initializing its value. |
| 212 | compiler::Node* AllocateHeapNumber(); |
| 213 | // Allocate a HeapNumber with a specific value. |
| 214 | compiler::Node* AllocateHeapNumberWithValue(compiler::Node* value); |
| 215 | // Allocate a SeqOneByteString with the given length. |
| 216 | compiler::Node* AllocateSeqOneByteString(int length); |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 217 | compiler::Node* AllocateSeqOneByteString(compiler::Node* context, |
| 218 | compiler::Node* length); |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 219 | // Allocate a SeqTwoByteString with the given length. |
| 220 | compiler::Node* AllocateSeqTwoByteString(int length); |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 221 | compiler::Node* AllocateSeqTwoByteString(compiler::Node* context, |
| 222 | compiler::Node* length); |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 223 | // Allocated an JSArray |
| 224 | compiler::Node* AllocateJSArray(ElementsKind kind, compiler::Node* array_map, |
| 225 | compiler::Node* capacity, |
| 226 | compiler::Node* length, |
| 227 | compiler::Node* allocation_site = nullptr, |
| 228 | ParameterMode mode = INTEGER_PARAMETERS); |
| 229 | |
| 230 | // Allocation site manipulation |
| 231 | void InitializeAllocationMemento(compiler::Node* base_allocation, |
| 232 | int base_allocation_size, |
| 233 | compiler::Node* allocation_site); |
| 234 | |
| 235 | compiler::Node* TruncateTaggedToFloat64(compiler::Node* context, |
| 236 | compiler::Node* value); |
| 237 | compiler::Node* TruncateTaggedToWord32(compiler::Node* context, |
| 238 | compiler::Node* value); |
| 239 | // Truncate the floating point value of a HeapNumber to an Int32. |
| 240 | compiler::Node* TruncateHeapNumberValueToWord32(compiler::Node* object); |
| 241 | |
| 242 | // Conversions. |
| 243 | compiler::Node* ChangeFloat64ToTagged(compiler::Node* value); |
| 244 | compiler::Node* ChangeInt32ToTagged(compiler::Node* value); |
| 245 | compiler::Node* ChangeUint32ToTagged(compiler::Node* value); |
| 246 | |
| 247 | // Type conversions. |
| 248 | // Throws a TypeError for {method_name} if {value} is not coercible to Object, |
| 249 | // or returns the {value} converted to a String otherwise. |
| 250 | compiler::Node* ToThisString(compiler::Node* context, compiler::Node* value, |
| 251 | char const* method_name); |
| 252 | |
| 253 | // String helpers. |
| 254 | // Load a character from a String (might flatten a ConsString). |
| 255 | compiler::Node* StringCharCodeAt(compiler::Node* string, |
| 256 | compiler::Node* smi_index); |
| 257 | // Return the single character string with only {code}. |
| 258 | compiler::Node* StringFromCharCode(compiler::Node* code); |
| 259 | |
| 260 | // Returns a node that is true if the given bit is set in |word32|. |
| 261 | template <typename T> |
| 262 | compiler::Node* BitFieldDecode(compiler::Node* word32) { |
| 263 | return BitFieldDecode(word32, T::kShift, T::kMask); |
| 264 | } |
| 265 | |
| 266 | compiler::Node* BitFieldDecode(compiler::Node* word32, uint32_t shift, |
| 267 | uint32_t mask); |
| 268 | |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 269 | void SetCounter(StatsCounter* counter, int value); |
| 270 | void IncrementCounter(StatsCounter* counter, int delta); |
| 271 | void DecrementCounter(StatsCounter* counter, int delta); |
| 272 | |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 273 | // Various building blocks for stubs doing property lookups. |
| 274 | void TryToName(compiler::Node* key, Label* if_keyisindex, Variable* var_index, |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 275 | Label* if_keyisunique, Label* if_bailout); |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 276 | |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 277 | // Calculates array index for given dictionary entry and entry field. |
| 278 | // See Dictionary::EntryToIndex(). |
| 279 | template <typename Dictionary> |
| 280 | compiler::Node* EntryToIndex(compiler::Node* entry, int field_index); |
| 281 | template <typename Dictionary> |
| 282 | compiler::Node* EntryToIndex(compiler::Node* entry) { |
| 283 | return EntryToIndex<Dictionary>(entry, Dictionary::kEntryKeyIndex); |
| 284 | } |
| 285 | |
| 286 | // Looks up an entry in a NameDictionaryBase successor. If the entry is found |
| 287 | // control goes to {if_found} and {var_name_index} contains an index of the |
| 288 | // key field of the entry found. If the key is not found control goes to |
| 289 | // {if_not_found}. |
| 290 | static const int kInlinedDictionaryProbes = 4; |
| 291 | template <typename Dictionary> |
| 292 | void NameDictionaryLookup(compiler::Node* dictionary, |
| 293 | compiler::Node* unique_name, Label* if_found, |
| 294 | Variable* var_name_index, Label* if_not_found, |
| 295 | int inlined_probes = kInlinedDictionaryProbes); |
| 296 | |
| 297 | compiler::Node* ComputeIntegerHash(compiler::Node* key, compiler::Node* seed); |
| 298 | |
| 299 | template <typename Dictionary> |
| 300 | void NumberDictionaryLookup(compiler::Node* dictionary, compiler::Node* key, |
| 301 | Label* if_found, Variable* var_entry, |
| 302 | Label* if_not_found); |
| 303 | |
| 304 | // Tries to check if {object} has own {unique_name} property. |
| 305 | void TryHasOwnProperty(compiler::Node* object, compiler::Node* map, |
| 306 | compiler::Node* instance_type, |
| 307 | compiler::Node* unique_name, Label* if_found, |
| 308 | Label* if_not_found, Label* if_bailout); |
| 309 | |
| 310 | // Tries to get {object}'s own {unique_name} property value. If the property |
| 311 | // is an accessor then it also calls a getter. If the property is a double |
| 312 | // field it re-wraps value in an immutable heap number. |
| 313 | void TryGetOwnProperty(compiler::Node* context, compiler::Node* receiver, |
| 314 | compiler::Node* object, compiler::Node* map, |
| 315 | compiler::Node* instance_type, |
| 316 | compiler::Node* unique_name, Label* if_found, |
| 317 | Variable* var_value, Label* if_not_found, |
| 318 | Label* if_bailout); |
| 319 | |
| 320 | void LoadPropertyFromFastObject(compiler::Node* object, compiler::Node* map, |
| 321 | compiler::Node* descriptors, |
| 322 | compiler::Node* name_index, |
| 323 | Variable* var_details, Variable* var_value); |
| 324 | |
| 325 | void LoadPropertyFromNameDictionary(compiler::Node* dictionary, |
| 326 | compiler::Node* entry, |
| 327 | Variable* var_details, |
| 328 | Variable* var_value); |
| 329 | |
| 330 | void LoadPropertyFromGlobalDictionary(compiler::Node* dictionary, |
| 331 | compiler::Node* entry, |
| 332 | Variable* var_details, |
| 333 | Variable* var_value, Label* if_deleted); |
| 334 | |
| 335 | // Generic property lookup generator. If the {object} is fast and |
| 336 | // {unique_name} property is found then the control goes to {if_found_fast} |
| 337 | // label and {var_meta_storage} and {var_name_index} will contain |
| 338 | // DescriptorArray and an index of the descriptor's name respectively. |
| 339 | // If the {object} is slow or global then the control goes to {if_found_dict} |
| 340 | // or {if_found_global} and the {var_meta_storage} and {var_name_index} will |
| 341 | // contain a dictionary and an index of the key field of the found entry. |
| 342 | // If property is not found or given lookup is not supported then |
| 343 | // the control goes to {if_not_found} or {if_bailout} respectively. |
| 344 | // |
| 345 | // Note: this code does not check if the global dictionary points to deleted |
| 346 | // entry! This has to be done by the caller. |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 347 | void TryLookupProperty(compiler::Node* object, compiler::Node* map, |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 348 | compiler::Node* instance_type, |
| 349 | compiler::Node* unique_name, Label* if_found_fast, |
| 350 | Label* if_found_dict, Label* if_found_global, |
| 351 | Variable* var_meta_storage, Variable* var_name_index, |
| 352 | Label* if_not_found, Label* if_bailout); |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 353 | |
| 354 | void TryLookupElement(compiler::Node* object, compiler::Node* map, |
| 355 | compiler::Node* instance_type, compiler::Node* index, |
| 356 | Label* if_found, Label* if_not_found, |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 357 | Label* if_bailout); |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 358 | |
| 359 | // Instanceof helpers. |
| 360 | // ES6 section 7.3.19 OrdinaryHasInstance (C, O) |
| 361 | compiler::Node* OrdinaryHasInstance(compiler::Node* context, |
| 362 | compiler::Node* callable, |
| 363 | compiler::Node* object); |
| 364 | |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 365 | // LoadIC helpers. |
| 366 | struct LoadICParameters { |
| 367 | LoadICParameters(compiler::Node* context, compiler::Node* receiver, |
| 368 | compiler::Node* name, compiler::Node* slot, |
| 369 | compiler::Node* vector) |
| 370 | : context(context), |
| 371 | receiver(receiver), |
| 372 | name(name), |
| 373 | slot(slot), |
| 374 | vector(vector) {} |
| 375 | |
| 376 | compiler::Node* context; |
| 377 | compiler::Node* receiver; |
| 378 | compiler::Node* name; |
| 379 | compiler::Node* slot; |
| 380 | compiler::Node* vector; |
| 381 | }; |
| 382 | |
| 383 | // Load type feedback vector from the stub caller's frame. |
| 384 | compiler::Node* LoadTypeFeedbackVectorForStub(); |
| 385 | |
| 386 | compiler::Node* LoadReceiverMap(compiler::Node* receiver); |
| 387 | |
| 388 | // Checks monomorphic case. Returns {feedback} entry of the vector. |
| 389 | compiler::Node* TryMonomorphicCase(const LoadICParameters* p, |
| 390 | compiler::Node* receiver_map, |
| 391 | Label* if_handler, Variable* var_handler, |
| 392 | Label* if_miss); |
| 393 | void HandlePolymorphicCase(const LoadICParameters* p, |
| 394 | compiler::Node* receiver_map, |
| 395 | compiler::Node* feedback, Label* if_handler, |
| 396 | Variable* var_handler, Label* if_miss, |
| 397 | int unroll_count); |
| 398 | |
| 399 | compiler::Node* StubCachePrimaryOffset(compiler::Node* name, |
| 400 | Code::Flags flags, |
| 401 | compiler::Node* map); |
| 402 | |
| 403 | compiler::Node* StubCacheSecondaryOffset(compiler::Node* name, |
| 404 | Code::Flags flags, |
| 405 | compiler::Node* seed); |
| 406 | |
| 407 | // This enum is used here as a replacement for StubCache::Table to avoid |
| 408 | // including stub cache header. |
| 409 | enum StubCacheTable : int; |
| 410 | |
| 411 | void TryProbeStubCacheTable(StubCache* stub_cache, StubCacheTable table_id, |
| 412 | compiler::Node* entry_offset, |
| 413 | compiler::Node* name, Code::Flags flags, |
| 414 | compiler::Node* map, Label* if_handler, |
| 415 | Variable* var_handler, Label* if_miss); |
| 416 | |
| 417 | void TryProbeStubCache(StubCache* stub_cache, Code::Flags flags, |
| 418 | compiler::Node* receiver, compiler::Node* name, |
| 419 | Label* if_handler, Variable* var_handler, |
| 420 | Label* if_miss); |
| 421 | |
| 422 | void LoadIC(const LoadICParameters* p); |
| 423 | void LoadGlobalIC(const LoadICParameters* p); |
| 424 | |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 425 | private: |
| 426 | compiler::Node* ElementOffsetFromIndex(compiler::Node* index, |
| 427 | ElementsKind kind, ParameterMode mode, |
| 428 | int base_size = 0); |
| 429 | |
| 430 | compiler::Node* AllocateRawAligned(compiler::Node* size_in_bytes, |
| 431 | AllocationFlags flags, |
| 432 | compiler::Node* top_address, |
| 433 | compiler::Node* limit_address); |
| 434 | compiler::Node* AllocateRawUnaligned(compiler::Node* size_in_bytes, |
| 435 | AllocationFlags flags, |
| 436 | compiler::Node* top_adddress, |
| 437 | compiler::Node* limit_address); |
| 438 | |
| 439 | static const int kElementLoopUnrollThreshold = 8; |
| 440 | }; |
| 441 | |
| 442 | } // namespace internal |
| 443 | } // namespace v8 |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 444 | #endif // V8_CODE_STUB_ASSEMBLER_H_ |