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 #include "src/base/optional.h"
6 #include "src/builtins/builtins-utils-gen.h"
7 #include "src/builtins/builtins.h"
8 #include "src/codegen/code-stub-assembler.h"
9 #include "src/ic/ic.h"
10 #include "src/ic/keyed-store-generic.h"
11 #include "src/objects/objects-inl.h"
12 #include "torque-generated/exported-macros-assembler.h"
13
14 namespace v8 {
15 namespace internal {
16
17 class HandlerBuiltinsAssembler : public CodeStubAssembler {
18 public:
HandlerBuiltinsAssembler(compiler::CodeAssemblerState * state)19 explicit HandlerBuiltinsAssembler(compiler::CodeAssemblerState* state)
20 : CodeStubAssembler(state) {}
21
22 protected:
23 void Generate_KeyedStoreIC_SloppyArguments();
24
25 // Essentially turns runtime elements kinds (TNode<Int32T>) into
26 // compile-time types (int) by dispatching over the runtime type and
27 // emitting a specialized copy of the given case function for each elements
28 // kind. Use with caution. This produces a *lot* of code.
29 using ElementsKindSwitchCase = std::function<void(ElementsKind)>;
30 void DispatchByElementsKind(TNode<Int32T> elements_kind,
31 const ElementsKindSwitchCase& case_function,
32 bool handle_typed_elements_kind);
33
34 // Dispatches over all possible combinations of {from,to} elements kinds.
35 using ElementsKindTransitionSwitchCase =
36 std::function<void(ElementsKind, ElementsKind)>;
37 void DispatchForElementsKindTransition(
38 TNode<Int32T> from_kind, TNode<Int32T> to_kind,
39 const ElementsKindTransitionSwitchCase& case_function);
40
41 void Generate_ElementsTransitionAndStore(KeyedAccessStoreMode store_mode);
42 void Generate_StoreFastElementIC(KeyedAccessStoreMode store_mode);
43 };
44
TF_BUILTIN(LoadIC_StringLength,CodeStubAssembler)45 TF_BUILTIN(LoadIC_StringLength, CodeStubAssembler) {
46 auto string = Parameter<String>(Descriptor::kReceiver);
47 Return(LoadStringLengthAsSmi(string));
48 }
49
TF_BUILTIN(LoadIC_StringWrapperLength,CodeStubAssembler)50 TF_BUILTIN(LoadIC_StringWrapperLength, CodeStubAssembler) {
51 auto value = Parameter<JSPrimitiveWrapper>(Descriptor::kReceiver);
52 TNode<String> string = CAST(LoadJSPrimitiveWrapperValue(value));
53 Return(LoadStringLengthAsSmi(string));
54 }
55
Generate_KeyedStoreIC_Megamorphic(compiler::CodeAssemblerState * state)56 void Builtins::Generate_KeyedStoreIC_Megamorphic(
57 compiler::CodeAssemblerState* state) {
58 KeyedStoreGenericGenerator::Generate(state);
59 }
60
Generate_DefineKeyedOwnIC_Megamorphic(compiler::CodeAssemblerState * state)61 void Builtins::Generate_DefineKeyedOwnIC_Megamorphic(
62 compiler::CodeAssemblerState* state) {
63 DefineKeyedOwnGenericGenerator::Generate(state);
64 }
65
Generate_StoreIC_NoFeedback(compiler::CodeAssemblerState * state)66 void Builtins::Generate_StoreIC_NoFeedback(
67 compiler::CodeAssemblerState* state) {
68 StoreICNoFeedbackGenerator::Generate(state);
69 }
70
Generate_DefineNamedOwnIC_NoFeedback(compiler::CodeAssemblerState * state)71 void Builtins::Generate_DefineNamedOwnIC_NoFeedback(
72 compiler::CodeAssemblerState* state) {
73 DefineNamedOwnICNoFeedbackGenerator::Generate(state);
74 }
75
76 // All possible fast-to-fast transitions. Transitions to dictionary mode are not
77 // handled by ElementsTransitionAndStore builtins.
78 #define ELEMENTS_KIND_TRANSITIONS(V) \
79 V(PACKED_SMI_ELEMENTS, HOLEY_SMI_ELEMENTS) \
80 V(PACKED_SMI_ELEMENTS, PACKED_DOUBLE_ELEMENTS) \
81 V(PACKED_SMI_ELEMENTS, HOLEY_DOUBLE_ELEMENTS) \
82 V(PACKED_SMI_ELEMENTS, PACKED_ELEMENTS) \
83 V(PACKED_SMI_ELEMENTS, HOLEY_ELEMENTS) \
84 V(HOLEY_SMI_ELEMENTS, HOLEY_DOUBLE_ELEMENTS) \
85 V(HOLEY_SMI_ELEMENTS, HOLEY_ELEMENTS) \
86 V(PACKED_DOUBLE_ELEMENTS, HOLEY_DOUBLE_ELEMENTS) \
87 V(PACKED_DOUBLE_ELEMENTS, PACKED_ELEMENTS) \
88 V(PACKED_DOUBLE_ELEMENTS, HOLEY_ELEMENTS) \
89 V(HOLEY_DOUBLE_ELEMENTS, HOLEY_ELEMENTS) \
90 V(PACKED_ELEMENTS, HOLEY_ELEMENTS)
91
DispatchForElementsKindTransition(TNode<Int32T> from_kind,TNode<Int32T> to_kind,const ElementsKindTransitionSwitchCase & case_function)92 void HandlerBuiltinsAssembler::DispatchForElementsKindTransition(
93 TNode<Int32T> from_kind, TNode<Int32T> to_kind,
94 const ElementsKindTransitionSwitchCase& case_function) {
95 STATIC_ASSERT(sizeof(ElementsKind) == sizeof(uint8_t));
96
97 Label next(this), if_unknown_type(this, Label::kDeferred);
98
99 int32_t combined_elements_kinds[] = {
100 #define ELEMENTS_KINDS_CASE(FROM, TO) (FROM << kBitsPerByte) | TO,
101 ELEMENTS_KIND_TRANSITIONS(ELEMENTS_KINDS_CASE)
102 #undef ELEMENTS_KINDS_CASE
103 };
104
105 #define ELEMENTS_KINDS_CASE(FROM, TO) Label if_##FROM##_##TO(this);
106 ELEMENTS_KIND_TRANSITIONS(ELEMENTS_KINDS_CASE)
107 #undef ELEMENTS_KINDS_CASE
108
109 Label* elements_kind_labels[] = {
110 #define ELEMENTS_KINDS_CASE(FROM, TO) &if_##FROM##_##TO,
111 ELEMENTS_KIND_TRANSITIONS(ELEMENTS_KINDS_CASE)
112 #undef ELEMENTS_KINDS_CASE
113 };
114 STATIC_ASSERT(arraysize(combined_elements_kinds) ==
115 arraysize(elements_kind_labels));
116
117 TNode<Int32T> combined_elements_kind =
118 Word32Or(Word32Shl(from_kind, Int32Constant(kBitsPerByte)), to_kind);
119
120 Switch(combined_elements_kind, &if_unknown_type, combined_elements_kinds,
121 elements_kind_labels, arraysize(combined_elements_kinds));
122
123 #define ELEMENTS_KINDS_CASE(FROM, TO) \
124 BIND(&if_##FROM##_##TO); \
125 { \
126 case_function(FROM, TO); \
127 Goto(&next); \
128 }
129 ELEMENTS_KIND_TRANSITIONS(ELEMENTS_KINDS_CASE)
130 #undef ELEMENTS_KINDS_CASE
131
132 BIND(&if_unknown_type);
133 Unreachable();
134
135 BIND(&next);
136 }
137
138 #undef ELEMENTS_KIND_TRANSITIONS
139
Generate_ElementsTransitionAndStore(KeyedAccessStoreMode store_mode)140 void HandlerBuiltinsAssembler::Generate_ElementsTransitionAndStore(
141 KeyedAccessStoreMode store_mode) {
142 using Descriptor = StoreTransitionDescriptor;
143 auto receiver = Parameter<JSObject>(Descriptor::kReceiver);
144 auto key = Parameter<Object>(Descriptor::kName);
145 auto value = Parameter<Object>(Descriptor::kValue);
146 auto map = Parameter<Map>(Descriptor::kMap);
147 auto slot = Parameter<Smi>(Descriptor::kSlot);
148 auto vector = Parameter<FeedbackVector>(Descriptor::kVector);
149 auto context = Parameter<Context>(Descriptor::kContext);
150
151 Comment("ElementsTransitionAndStore: store_mode=", store_mode);
152
153 Label miss(this);
154
155 if (FLAG_trace_elements_transitions) {
156 // Tracing elements transitions is the job of the runtime.
157 Goto(&miss);
158 } else {
159 // TODO(v8:8481): Pass from_kind and to_kind in feedback vector slots.
160 DispatchForElementsKindTransition(
161 LoadElementsKind(receiver), LoadMapElementsKind(map),
162 [=, &miss](ElementsKind from_kind, ElementsKind to_kind) {
163 TransitionElementsKind(receiver, map, from_kind, to_kind, &miss);
164 EmitElementStore(receiver, key, value, to_kind, store_mode, &miss,
165 context, nullptr);
166 });
167 Return(value);
168 }
169
170 BIND(&miss);
171 TailCallRuntime(Runtime::kElementsTransitionAndStoreIC_Miss, context,
172 receiver, key, value, map, slot, vector);
173 }
174
TF_BUILTIN(ElementsTransitionAndStore_Standard,HandlerBuiltinsAssembler)175 TF_BUILTIN(ElementsTransitionAndStore_Standard, HandlerBuiltinsAssembler) {
176 Generate_ElementsTransitionAndStore(STANDARD_STORE);
177 }
178
TF_BUILTIN(ElementsTransitionAndStore_GrowNoTransitionHandleCOW,HandlerBuiltinsAssembler)179 TF_BUILTIN(ElementsTransitionAndStore_GrowNoTransitionHandleCOW,
180 HandlerBuiltinsAssembler) {
181 Generate_ElementsTransitionAndStore(STORE_AND_GROW_HANDLE_COW);
182 }
183
TF_BUILTIN(ElementsTransitionAndStore_NoTransitionIgnoreOOB,HandlerBuiltinsAssembler)184 TF_BUILTIN(ElementsTransitionAndStore_NoTransitionIgnoreOOB,
185 HandlerBuiltinsAssembler) {
186 Generate_ElementsTransitionAndStore(STORE_IGNORE_OUT_OF_BOUNDS);
187 }
188
TF_BUILTIN(ElementsTransitionAndStore_NoTransitionHandleCOW,HandlerBuiltinsAssembler)189 TF_BUILTIN(ElementsTransitionAndStore_NoTransitionHandleCOW,
190 HandlerBuiltinsAssembler) {
191 Generate_ElementsTransitionAndStore(STORE_HANDLE_COW);
192 }
193
194 // All elements kinds handled by EmitElementStore. Specifically, this includes
195 // fast elements and fixed typed array elements.
196 #define ELEMENTS_KINDS(V) \
197 V(PACKED_SMI_ELEMENTS) \
198 V(HOLEY_SMI_ELEMENTS) \
199 V(PACKED_ELEMENTS) \
200 V(PACKED_NONEXTENSIBLE_ELEMENTS) \
201 V(PACKED_SEALED_ELEMENTS) \
202 V(HOLEY_ELEMENTS) \
203 V(HOLEY_NONEXTENSIBLE_ELEMENTS) \
204 V(HOLEY_SEALED_ELEMENTS) \
205 V(PACKED_DOUBLE_ELEMENTS) \
206 V(HOLEY_DOUBLE_ELEMENTS) \
207 V(UINT8_ELEMENTS) \
208 V(INT8_ELEMENTS) \
209 V(UINT16_ELEMENTS) \
210 V(INT16_ELEMENTS) \
211 V(UINT32_ELEMENTS) \
212 V(INT32_ELEMENTS) \
213 V(FLOAT32_ELEMENTS) \
214 V(FLOAT64_ELEMENTS) \
215 V(UINT8_CLAMPED_ELEMENTS) \
216 V(BIGUINT64_ELEMENTS) \
217 V(BIGINT64_ELEMENTS) \
218 V(RAB_GSAB_UINT8_ELEMENTS) \
219 V(RAB_GSAB_INT8_ELEMENTS) \
220 V(RAB_GSAB_UINT16_ELEMENTS) \
221 V(RAB_GSAB_INT16_ELEMENTS) \
222 V(RAB_GSAB_UINT32_ELEMENTS) \
223 V(RAB_GSAB_INT32_ELEMENTS) \
224 V(RAB_GSAB_FLOAT32_ELEMENTS) \
225 V(RAB_GSAB_FLOAT64_ELEMENTS) \
226 V(RAB_GSAB_UINT8_CLAMPED_ELEMENTS) \
227 V(RAB_GSAB_BIGUINT64_ELEMENTS) \
228 V(RAB_GSAB_BIGINT64_ELEMENTS)
229
DispatchByElementsKind(TNode<Int32T> elements_kind,const ElementsKindSwitchCase & case_function,bool handle_typed_elements_kind)230 void HandlerBuiltinsAssembler::DispatchByElementsKind(
231 TNode<Int32T> elements_kind, const ElementsKindSwitchCase& case_function,
232 bool handle_typed_elements_kind) {
233 Label next(this), if_unknown_type(this, Label::kDeferred);
234
235 int32_t elements_kinds[] = {
236 #define ELEMENTS_KINDS_CASE(KIND) KIND,
237 ELEMENTS_KINDS(ELEMENTS_KINDS_CASE)
238 #undef ELEMENTS_KINDS_CASE
239 };
240
241 #define ELEMENTS_KINDS_CASE(KIND) Label if_##KIND(this);
242 ELEMENTS_KINDS(ELEMENTS_KINDS_CASE)
243 #undef ELEMENTS_KINDS_CASE
244
245 Label* elements_kind_labels[] = {
246 #define ELEMENTS_KINDS_CASE(KIND) &if_##KIND,
247 ELEMENTS_KINDS(ELEMENTS_KINDS_CASE)
248 #undef ELEMENTS_KINDS_CASE
249 };
250 STATIC_ASSERT(arraysize(elements_kinds) == arraysize(elements_kind_labels));
251
252 // TODO(mythria): Do not emit cases for typed elements kind when
253 // handle_typed_elements is false to decrease the size of the jump table.
254 Switch(elements_kind, &if_unknown_type, elements_kinds, elements_kind_labels,
255 arraysize(elements_kinds));
256
257 #define ELEMENTS_KINDS_CASE(KIND) \
258 BIND(&if_##KIND); \
259 { \
260 if (!FLAG_enable_sealed_frozen_elements_kind && \
261 IsAnyNonextensibleElementsKindUnchecked(KIND)) { \
262 /* Disable support for frozen or sealed elements kinds. */ \
263 Unreachable(); \
264 } else if (!handle_typed_elements_kind && \
265 IsTypedArrayOrRabGsabTypedArrayElementsKind(KIND)) { \
266 Unreachable(); \
267 } else { \
268 case_function(KIND); \
269 Goto(&next); \
270 } \
271 }
272 ELEMENTS_KINDS(ELEMENTS_KINDS_CASE)
273 #undef ELEMENTS_KINDS_CASE
274
275 BIND(&if_unknown_type);
276 Unreachable();
277
278 BIND(&next);
279 }
280
281 #undef ELEMENTS_KINDS
282
Generate_StoreFastElementIC(KeyedAccessStoreMode store_mode)283 void HandlerBuiltinsAssembler::Generate_StoreFastElementIC(
284 KeyedAccessStoreMode store_mode) {
285 using Descriptor = StoreWithVectorDescriptor;
286 auto receiver = Parameter<JSObject>(Descriptor::kReceiver);
287 auto key = Parameter<Object>(Descriptor::kName);
288 auto value = Parameter<Object>(Descriptor::kValue);
289 auto slot = Parameter<Smi>(Descriptor::kSlot);
290 auto vector = Parameter<HeapObject>(Descriptor::kVector);
291 auto context = Parameter<Context>(Descriptor::kContext);
292
293 Comment("StoreFastElementStub: store_mode=", store_mode);
294
295 Label miss(this);
296
297 bool handle_typed_elements_kind =
298 store_mode == STANDARD_STORE || store_mode == STORE_IGNORE_OUT_OF_BOUNDS;
299 // For typed arrays maybe_converted_value contains the value obtained after
300 // calling ToNumber. We should pass the converted value to the runtime to
301 // avoid doing the user visible conversion again.
302 TVARIABLE(Object, maybe_converted_value, value);
303 // TODO(v8:8481): Pass elements_kind in feedback vector slots.
304 DispatchByElementsKind(
305 LoadElementsKind(receiver),
306 [=, &miss, &maybe_converted_value](ElementsKind elements_kind) {
307 EmitElementStore(receiver, key, value, elements_kind, store_mode, &miss,
308 context, &maybe_converted_value);
309 },
310 handle_typed_elements_kind);
311 Return(value);
312
313 BIND(&miss);
314 TailCallRuntime(Runtime::kKeyedStoreIC_Miss, context,
315 maybe_converted_value.value(), slot, vector, receiver, key);
316 }
317
TF_BUILTIN(StoreFastElementIC_Standard,HandlerBuiltinsAssembler)318 TF_BUILTIN(StoreFastElementIC_Standard, HandlerBuiltinsAssembler) {
319 Generate_StoreFastElementIC(STANDARD_STORE);
320 }
321
TF_BUILTIN(StoreFastElementIC_GrowNoTransitionHandleCOW,HandlerBuiltinsAssembler)322 TF_BUILTIN(StoreFastElementIC_GrowNoTransitionHandleCOW,
323 HandlerBuiltinsAssembler) {
324 Generate_StoreFastElementIC(STORE_AND_GROW_HANDLE_COW);
325 }
326
TF_BUILTIN(StoreFastElementIC_NoTransitionIgnoreOOB,HandlerBuiltinsAssembler)327 TF_BUILTIN(StoreFastElementIC_NoTransitionIgnoreOOB, HandlerBuiltinsAssembler) {
328 Generate_StoreFastElementIC(STORE_IGNORE_OUT_OF_BOUNDS);
329 }
330
TF_BUILTIN(StoreFastElementIC_NoTransitionHandleCOW,HandlerBuiltinsAssembler)331 TF_BUILTIN(StoreFastElementIC_NoTransitionHandleCOW, HandlerBuiltinsAssembler) {
332 Generate_StoreFastElementIC(STORE_HANDLE_COW);
333 }
334
TF_BUILTIN(LoadIC_FunctionPrototype,CodeStubAssembler)335 TF_BUILTIN(LoadIC_FunctionPrototype, CodeStubAssembler) {
336 auto receiver = Parameter<JSFunction>(Descriptor::kReceiver);
337 auto name = Parameter<Name>(Descriptor::kName);
338 auto slot = Parameter<Smi>(Descriptor::kSlot);
339 auto vector = Parameter<FeedbackVector>(Descriptor::kVector);
340 auto context = Parameter<Context>(Descriptor::kContext);
341
342 Label miss(this, Label::kDeferred);
343 Return(LoadJSFunctionPrototype(receiver, &miss));
344
345 BIND(&miss);
346 TailCallRuntime(Runtime::kLoadIC_Miss, context, receiver, name, slot, vector);
347 }
348
TF_BUILTIN(StoreGlobalIC_Slow,CodeStubAssembler)349 TF_BUILTIN(StoreGlobalIC_Slow, CodeStubAssembler) {
350 auto receiver = Parameter<Object>(Descriptor::kReceiver);
351 auto name = Parameter<Name>(Descriptor::kName);
352 auto value = Parameter<Object>(Descriptor::kValue);
353 auto slot = Parameter<Smi>(Descriptor::kSlot);
354 auto vector = Parameter<FeedbackVector>(Descriptor::kVector);
355 auto context = Parameter<Context>(Descriptor::kContext);
356
357 // The slow case calls into the runtime to complete the store without causing
358 // an IC miss that would otherwise cause a transition to the generic stub.
359 TailCallRuntime(Runtime::kStoreGlobalIC_Slow, context, value, slot, vector,
360 receiver, name);
361 }
362
TF_BUILTIN(KeyedLoadIC_SloppyArguments,HandlerBuiltinsAssembler)363 TF_BUILTIN(KeyedLoadIC_SloppyArguments, HandlerBuiltinsAssembler) {
364 auto receiver = Parameter<JSObject>(Descriptor::kReceiver);
365 auto key = Parameter<Object>(Descriptor::kName);
366 auto slot = Parameter<Smi>(Descriptor::kSlot);
367 auto vector = Parameter<HeapObject>(Descriptor::kVector);
368 auto context = Parameter<Context>(Descriptor::kContext);
369
370 Label miss(this);
371
372 TNode<Object> result = SloppyArgumentsLoad(receiver, key, &miss);
373 Return(result);
374
375 BIND(&miss);
376 {
377 Comment("Miss");
378 TailCallRuntime(Runtime::kKeyedLoadIC_Miss, context, receiver, key, slot,
379 vector);
380 }
381 }
382
Generate_KeyedStoreIC_SloppyArguments()383 void HandlerBuiltinsAssembler::Generate_KeyedStoreIC_SloppyArguments() {
384 using Descriptor = StoreWithVectorDescriptor;
385 auto receiver = Parameter<JSObject>(Descriptor::kReceiver);
386 auto key = Parameter<Object>(Descriptor::kName);
387 auto value = Parameter<Object>(Descriptor::kValue);
388 auto slot = Parameter<Smi>(Descriptor::kSlot);
389 auto vector = Parameter<HeapObject>(Descriptor::kVector);
390 auto context = Parameter<Context>(Descriptor::kContext);
391
392 Label miss(this);
393
394 SloppyArgumentsStore(receiver, key, value, &miss);
395 Return(value);
396
397 BIND(&miss);
398 TailCallRuntime(Runtime::kKeyedStoreIC_Miss, context, value, slot, vector,
399 receiver, key);
400 }
401
TF_BUILTIN(KeyedStoreIC_SloppyArguments_Standard,HandlerBuiltinsAssembler)402 TF_BUILTIN(KeyedStoreIC_SloppyArguments_Standard, HandlerBuiltinsAssembler) {
403 Generate_KeyedStoreIC_SloppyArguments();
404 }
405
TF_BUILTIN(KeyedStoreIC_SloppyArguments_GrowNoTransitionHandleCOW,HandlerBuiltinsAssembler)406 TF_BUILTIN(KeyedStoreIC_SloppyArguments_GrowNoTransitionHandleCOW,
407 HandlerBuiltinsAssembler) {
408 Generate_KeyedStoreIC_SloppyArguments();
409 }
410
TF_BUILTIN(KeyedStoreIC_SloppyArguments_NoTransitionIgnoreOOB,HandlerBuiltinsAssembler)411 TF_BUILTIN(KeyedStoreIC_SloppyArguments_NoTransitionIgnoreOOB,
412 HandlerBuiltinsAssembler) {
413 Generate_KeyedStoreIC_SloppyArguments();
414 }
415
TF_BUILTIN(KeyedStoreIC_SloppyArguments_NoTransitionHandleCOW,HandlerBuiltinsAssembler)416 TF_BUILTIN(KeyedStoreIC_SloppyArguments_NoTransitionHandleCOW,
417 HandlerBuiltinsAssembler) {
418 Generate_KeyedStoreIC_SloppyArguments();
419 }
420
TF_BUILTIN(LoadIndexedInterceptorIC,CodeStubAssembler)421 TF_BUILTIN(LoadIndexedInterceptorIC, CodeStubAssembler) {
422 auto receiver = Parameter<JSObject>(Descriptor::kReceiver);
423 auto key = Parameter<Object>(Descriptor::kName);
424 auto slot = Parameter<Smi>(Descriptor::kSlot);
425 auto vector = Parameter<HeapObject>(Descriptor::kVector);
426 auto context = Parameter<Context>(Descriptor::kContext);
427
428 Label if_keyispositivesmi(this), if_keyisinvalid(this);
429 Branch(TaggedIsPositiveSmi(key), &if_keyispositivesmi, &if_keyisinvalid);
430 BIND(&if_keyispositivesmi);
431 TailCallRuntime(Runtime::kLoadElementWithInterceptor, context, receiver, key);
432
433 BIND(&if_keyisinvalid);
434 TailCallRuntime(Runtime::kKeyedLoadIC_Miss, context, receiver, key, slot,
435 vector);
436 }
437
TF_BUILTIN(KeyedHasIC_SloppyArguments,HandlerBuiltinsAssembler)438 TF_BUILTIN(KeyedHasIC_SloppyArguments, HandlerBuiltinsAssembler) {
439 auto receiver = Parameter<JSObject>(Descriptor::kReceiver);
440 auto key = Parameter<Object>(Descriptor::kName);
441 auto slot = Parameter<Smi>(Descriptor::kSlot);
442 auto vector = Parameter<HeapObject>(Descriptor::kVector);
443 auto context = Parameter<Context>(Descriptor::kContext);
444
445 Label miss(this);
446
447 TNode<Object> result = SloppyArgumentsHas(receiver, key, &miss);
448 Return(result);
449
450 BIND(&miss);
451 {
452 Comment("Miss");
453 TailCallRuntime(Runtime::kKeyedHasIC_Miss, context, receiver, key, slot,
454 vector);
455 }
456 }
457
TF_BUILTIN(HasIndexedInterceptorIC,CodeStubAssembler)458 TF_BUILTIN(HasIndexedInterceptorIC, CodeStubAssembler) {
459 auto receiver = Parameter<JSObject>(Descriptor::kReceiver);
460 auto key = Parameter<Object>(Descriptor::kName);
461 auto slot = Parameter<Smi>(Descriptor::kSlot);
462 auto vector = Parameter<HeapObject>(Descriptor::kVector);
463 auto context = Parameter<Context>(Descriptor::kContext);
464
465 Label if_keyispositivesmi(this), if_keyisinvalid(this);
466 Branch(TaggedIsPositiveSmi(key), &if_keyispositivesmi, &if_keyisinvalid);
467 BIND(&if_keyispositivesmi);
468 TailCallRuntime(Runtime::kHasElementWithInterceptor, context, receiver, key);
469
470 BIND(&if_keyisinvalid);
471 TailCallRuntime(Runtime::kKeyedHasIC_Miss, context, receiver, key, slot,
472 vector);
473 }
474
475 } // namespace internal
476 } // namespace v8
477