• 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_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