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