5 #include "src/ic/accessor-assembler.h" 7 #include "src/ast/ast.h" 8 #include "src/code-factory.h" 9 #include "src/code-stubs.h" 10 #include "src/counters.h" 11 #include "src/ic/handler-configuration.h" 12 #include "src/ic/ic.h" 13 #include "src/ic/keyed-store-generic.h" 14 #include "src/ic/stub-cache.h" 15 #include "src/objects-inl.h" 16 #include "src/objects/module.h" 17 #include "src/objects/smi.h" 22 using compiler::CodeAssemblerState;
25 using TNode = compiler::TNode<T>;
27 using SloppyTNode = compiler::SloppyTNode<T>;
32 TNode<MaybeObject> AccessorAssembler::LoadHandlerDataField(
33 SloppyTNode<DataHandler> handler,
int data_index) {
35 TNode<Map> handler_map = LoadMap(handler);
36 TNode<Int32T> instance_type = LoadMapInstanceType(handler_map);
39 Word32Or(InstanceTypeEqual(instance_type, LOAD_HANDLER_TYPE),
40 InstanceTypeEqual(instance_type, STORE_HANDLER_TYPE)));
45 offset = DataHandler::kData1Offset;
46 minimum_size = DataHandler::kSizeWithData1;
49 offset = DataHandler::kData2Offset;
50 minimum_size = DataHandler::kSizeWithData2;
53 offset = DataHandler::kData3Offset;
54 minimum_size = DataHandler::kSizeWithData3;
61 CSA_ASSERT(
this, UintPtrGreaterThanOrEqual(
62 LoadMapInstanceSizeInWords(handler_map),
63 IntPtrConstant(minimum_size / kPointerSize)));
64 return LoadMaybeWeakObjectField(handler, offset);
67 TNode<MaybeObject> AccessorAssembler::TryMonomorphicCase(
68 Node* slot, Node* vector, Node* receiver_map, Label* if_handler,
69 TVariable<MaybeObject>* var_handler, Label* if_miss) {
70 Comment(
"TryMonomorphicCase");
71 DCHECK_EQ(MachineRepresentation::kTagged, var_handler->rep());
75 CSA_ASSERT(
this, IsFeedbackVector(vector), vector);
76 int32_t header_size = FeedbackVector::kFeedbackSlotsOffset - kHeapObjectTag;
80 Node* offset = ElementOffsetFromIndex(slot, HOLEY_ELEMENTS, SMI_PARAMETERS);
81 TNode<MaybeObject> feedback = ReinterpretCast<MaybeObject>(
82 Load(MachineType::AnyTagged(), vector,
83 IntPtrAdd(offset, IntPtrConstant(header_size))));
87 GotoIf(IsNotWeakReferenceTo(feedback, CAST(receiver_map)), if_miss);
89 TNode<MaybeObject> handler = UncheckedCast<MaybeObject>(
90 Load(MachineType::AnyTagged(), vector,
91 IntPtrAdd(offset, IntPtrConstant(header_size + kPointerSize))));
93 *var_handler = handler;
98 void AccessorAssembler::HandlePolymorphicCase(
99 Node* receiver_map, TNode<WeakFixedArray> feedback, Label* if_handler,
100 TVariable<MaybeObject>* var_handler, Label* if_miss,
101 int min_feedback_capacity) {
102 Comment(
"HandlePolymorphicCase");
103 DCHECK_EQ(MachineRepresentation::kTagged, var_handler->rep());
107 Label loop(
this, Label::kDeferred);
110 const int kEntrySize = 2;
114 Node* length =
nullptr;
115 CSA_ASSERT(
this, SmiGreaterThanOrEqual(
116 LoadWeakFixedArrayLength(feedback),
117 SmiConstant(min_feedback_capacity * kEntrySize)));
119 const int kUnrolledIterations = IC::kMaxPolymorphicMapCount;
120 for (
int i = 0;
i < kUnrolledIterations;
i++) {
121 int map_index =
i * kEntrySize;
122 int handler_index =
i * kEntrySize + 1;
124 if (
i >= min_feedback_capacity) {
125 if (length ==
nullptr) length = LoadWeakFixedArrayLength(feedback);
126 GotoIf(SmiGreaterThanOrEqual(SmiConstant(handler_index), CAST(length)),
130 Label next_entry(
this);
131 TNode<MaybeObject> maybe_cached_map =
132 LoadWeakFixedArrayElement(feedback, map_index);
133 CSA_ASSERT(
this, IsWeakOrCleared(maybe_cached_map));
134 GotoIf(IsNotWeakReferenceTo(maybe_cached_map, CAST(receiver_map)),
138 TNode<MaybeObject> handler =
139 LoadWeakFixedArrayElement(feedback, handler_index);
140 *var_handler = handler;
149 Node* start_index = IntPtrConstant(kUnrolledIterations * kEntrySize);
150 Node* end_index = LoadAndUntagWeakFixedArrayLength(feedback);
152 start_index, end_index,
153 [
this, receiver_map, feedback, if_handler, var_handler](Node* index) {
154 Label next_entry(
this);
155 TNode<MaybeObject> maybe_cached_map =
156 LoadWeakFixedArrayElement(feedback, index);
157 CSA_ASSERT(
this, IsWeakOrCleared(maybe_cached_map));
158 GotoIf(IsNotWeakReferenceTo(maybe_cached_map, CAST(receiver_map)),
162 TNode<MaybeObject> handler =
163 LoadWeakFixedArrayElement(feedback, index, kPointerSize);
164 *var_handler = handler;
169 kEntrySize, INTPTR_PARAMETERS, IndexAdvanceMode::kPost);
174 void AccessorAssembler::HandleLoadICHandlerCase(
175 const LoadICParameters* p, TNode<Object> handler, Label* miss,
176 ExitPoint* exit_point, ICMode ic_mode, OnNonExistent on_nonexistent,
177 ElementSupport support_elements) {
178 Comment(
"have_handler");
180 VARIABLE(var_holder, MachineRepresentation::kTagged, p->holder);
181 VARIABLE(var_smi_handler, MachineRepresentation::kTagged, handler);
183 Variable* vars[] = {&var_holder, &var_smi_handler};
184 Label if_smi_handler(
this, 2, vars);
185 Label try_proto_handler(
this, Label::kDeferred),
186 call_handler(
this, Label::kDeferred);
188 Branch(TaggedIsSmi(handler), &if_smi_handler, &try_proto_handler);
192 BIND(&if_smi_handler);
194 HandleLoadICSmiHandlerCase(p, var_holder.value(), var_smi_handler.value(),
195 handler, miss, exit_point, on_nonexistent,
199 BIND(&try_proto_handler);
201 GotoIf(IsCodeMap(LoadMap(CAST(handler))), &call_handler);
202 HandleLoadICProtoHandler(p, handler, &var_holder, &var_smi_handler,
203 &if_smi_handler, miss, exit_point, ic_mode);
208 exit_point->ReturnCallStub(LoadWithVectorDescriptor{}, handler, p->context,
209 p->receiver, p->name, p->slot, p->vector);
213 void AccessorAssembler::HandleLoadCallbackProperty(
const LoadICParameters* p,
214 TNode<JSObject> holder,
215 TNode<WordT> handler_word,
216 ExitPoint* exit_point) {
217 Comment(
"native_data_property_load");
218 TNode<IntPtrT> descriptor =
219 Signed(DecodeWord<LoadHandler::DescriptorBits>(handler_word));
221 Label runtime(
this, Label::kDeferred);
222 Callable callable = CodeFactory::ApiGetter(isolate());
223 TNode<AccessorInfo> accessor_info =
224 CAST(LoadDescriptorValue(LoadMap(holder), descriptor));
226 GotoIf(IsRuntimeCallStatsEnabled(), &runtime);
227 exit_point->ReturnCallStub(callable, p->context, p->receiver, holder,
231 exit_point->ReturnCallRuntime(Runtime::kLoadCallbackProperty, p->context,
232 p->receiver, holder, accessor_info, p->name);
235 void AccessorAssembler::HandleLoadAccessor(
236 const LoadICParameters* p, TNode<CallHandlerInfo> call_handler_info,
237 TNode<WordT> handler_word, TNode<DataHandler> handler,
238 TNode<IntPtrT> handler_kind, ExitPoint* exit_point) {
239 Comment(
"api_getter");
240 Label runtime(
this, Label::kDeferred);
243 TNode<MaybeObject> maybe_context = Select<MaybeObject>(
244 IsSetWord<LoadHandler::DoAccessCheckOnReceiverBits>(handler_word),
245 [=] {
return LoadHandlerDataField(handler, 3); },
246 [=] {
return LoadHandlerDataField(handler, 2); });
248 CSA_ASSERT(
this, IsWeakOrCleared(maybe_context));
249 CSA_CHECK(
this, IsNotCleared(maybe_context));
250 TNode<Object> context = GetHeapObjectAssumeWeak(maybe_context);
252 GotoIf(IsRuntimeCallStatsEnabled(), &runtime);
254 TNode<Foreign> foreign = CAST(
255 LoadObjectField(call_handler_info, CallHandlerInfo::kJsCallbackOffset));
256 TNode<WordT> callback = TNode<WordT>::UncheckedCast(LoadObjectField(
257 foreign, Foreign::kForeignAddressOffset, MachineType::Pointer()));
259 LoadObjectField(call_handler_info, CallHandlerInfo::kDataOffset);
261 VARIABLE(api_holder, MachineRepresentation::kTagged, p->receiver);
263 GotoIf(WordEqual(handler_kind, IntPtrConstant(LoadHandler::kApiGetter)),
268 WordEqual(handler_kind,
269 IntPtrConstant(LoadHandler::kApiGetterHolderIsPrototype)));
271 api_holder.Bind(LoadMapPrototype(LoadMap(p->receiver)));
275 Callable callable = CodeFactory::CallApiCallback(isolate(), 0);
276 exit_point->Return(CallStub(callable,
nullptr, context, data,
277 api_holder.value(), callback, p->receiver));
281 exit_point->ReturnCallRuntime(Runtime::kLoadAccessorProperty, context,
282 p->receiver, SmiTag(handler_kind),
286 void AccessorAssembler::HandleLoadField(Node* holder, Node* handler_word,
287 Variable* var_double_value,
289 ExitPoint* exit_point) {
290 Comment(
"field_load");
291 Node* index = DecodeWord<LoadHandler::FieldIndexBits>(handler_word);
292 Node* offset = IntPtrMul(index, IntPtrConstant(kPointerSize));
294 Label inobject(
this), out_of_object(
this);
295 Branch(IsSetWord<LoadHandler::IsInobjectBits>(handler_word), &inobject,
300 Label is_double(
this);
301 GotoIf(IsSetWord<LoadHandler::IsDoubleBits>(handler_word), &is_double);
302 exit_point->Return(LoadObjectField(holder, offset));
305 if (FLAG_unbox_double_fields) {
306 var_double_value->Bind(
307 LoadObjectField(holder, offset, MachineType::Float64()));
309 Node* mutable_heap_number = LoadObjectField(holder, offset);
310 var_double_value->Bind(LoadHeapNumberValue(mutable_heap_number));
315 BIND(&out_of_object);
317 Label is_double(
this);
318 Node* properties = LoadFastProperties(holder);
319 Node* value = LoadObjectField(properties, offset);
320 GotoIf(IsSetWord<LoadHandler::IsDoubleBits>(handler_word), &is_double);
321 exit_point->Return(value);
324 var_double_value->Bind(LoadHeapNumberValue(value));
329 TNode<Object> AccessorAssembler::LoadDescriptorValue(
330 TNode<Map> map, TNode<IntPtrT> descriptor_entry) {
331 return CAST(LoadDescriptorValueOrFieldType(map, descriptor_entry));
334 TNode<MaybeObject> AccessorAssembler::LoadDescriptorValueOrFieldType(
335 TNode<Map> map, TNode<IntPtrT> descriptor_entry) {
336 TNode<DescriptorArray> descriptors = LoadMapDescriptors(map);
337 return LoadFieldTypeByDescriptorEntry(descriptors, descriptor_entry);
340 void AccessorAssembler::HandleLoadICSmiHandlerCase(
341 const LoadICParameters* p, Node* holder, SloppyTNode<Smi> smi_handler,
342 SloppyTNode<Object> handler, Label* miss, ExitPoint* exit_point,
343 OnNonExistent on_nonexistent, ElementSupport support_elements) {
344 VARIABLE(var_double_value, MachineRepresentation::kFloat64);
345 Label rebox_double(
this, &var_double_value);
347 TNode<WordT> handler_word = SmiUntag(smi_handler);
348 TNode<IntPtrT> handler_kind =
349 Signed(DecodeWord<LoadHandler::KindBits>(handler_word));
350 if (support_elements == kSupportElements) {
351 Label if_element(
this), if_indexed_string(
this), if_property(
this);
352 GotoIf(WordEqual(handler_kind, IntPtrConstant(LoadHandler::kElement)),
354 Branch(WordEqual(handler_kind, IntPtrConstant(LoadHandler::kIndexedString)),
355 &if_indexed_string, &if_property);
358 Comment(
"element_load");
359 Node* intptr_index = TryToIntptr(p->name, miss);
360 Node* elements = LoadElements(holder);
361 Node* is_jsarray_condition =
362 IsSetWord<LoadHandler::IsJsArrayBits>(handler_word);
363 Node* elements_kind =
364 DecodeWord32FromWord<LoadHandler::ElementsKindBits>(handler_word);
365 Label if_hole(
this), unimplemented_elements_kind(
this),
366 if_oob(
this, Label::kDeferred);
367 EmitElementLoad(holder, elements, elements_kind, intptr_index,
368 is_jsarray_condition, &if_hole, &rebox_double,
369 &var_double_value, &unimplemented_elements_kind, &if_oob,
372 BIND(&unimplemented_elements_kind);
382 Comment(
"out of bounds elements access");
383 Label return_undefined(
this);
386 Node* allow_out_of_bounds =
387 IsSetWord<LoadHandler::AllowOutOfBoundsBits>(handler_word);
388 GotoIfNot(allow_out_of_bounds, miss);
395 GotoIf(IsJSTypedArray(holder), &return_undefined);
396 GotoIf(IntPtrLessThan(intptr_index, IntPtrConstant(0)), miss);
400 BranchIfPrototypesHaveNoElements(LoadMap(holder), &return_undefined,
403 BIND(&return_undefined);
404 exit_point->Return(UndefinedConstant());
409 Comment(
"convert hole");
410 GotoIfNot(IsSetWord<LoadHandler::ConvertHoleBits>(handler_word), miss);
411 GotoIf(IsNoElementsProtectorCellInvalid(), miss);
412 exit_point->Return(UndefinedConstant());
415 BIND(&if_indexed_string);
417 Label if_oob(
this, Label::kDeferred);
419 Comment(
"indexed string");
420 Node* intptr_index = TryToIntptr(p->name, miss);
421 Node* length = LoadStringLengthAsWord(holder);
422 GotoIf(UintPtrGreaterThanOrEqual(intptr_index, length), &if_oob);
423 TNode<Int32T> code = StringCharCodeAt(holder, intptr_index);
424 TNode<String> result = StringFromSingleCharCode(code);
428 Node* allow_out_of_bounds =
429 IsSetWord<LoadHandler::AllowOutOfBoundsBits>(handler_word);
430 GotoIfNot(allow_out_of_bounds, miss);
431 GotoIf(IsNoElementsProtectorCellInvalid(), miss);
432 Return(UndefinedConstant());
436 Comment(
"property_load");
439 Label constant(
this), field(
this), normal(
this, Label::kDeferred),
440 interceptor(
this, Label::kDeferred), nonexistent(
this),
441 accessor(
this, Label::kDeferred), global(
this, Label::kDeferred),
442 module_export(
this, Label::kDeferred), proxy(
this, Label::kDeferred),
443 native_data_property(
this), api_getter(
this);
444 GotoIf(WordEqual(handler_kind, IntPtrConstant(LoadHandler::kField)), &field);
446 GotoIf(WordEqual(handler_kind, IntPtrConstant(LoadHandler::kConstant)),
449 GotoIf(WordEqual(handler_kind, IntPtrConstant(LoadHandler::kNonExistent)),
452 GotoIf(WordEqual(handler_kind, IntPtrConstant(LoadHandler::kNormal)),
455 GotoIf(WordEqual(handler_kind, IntPtrConstant(LoadHandler::kAccessor)),
459 WordEqual(handler_kind, IntPtrConstant(LoadHandler::kNativeDataProperty)),
460 &native_data_property);
462 GotoIf(WordEqual(handler_kind, IntPtrConstant(LoadHandler::kApiGetter)),
465 GotoIf(WordEqual(handler_kind,
466 IntPtrConstant(LoadHandler::kApiGetterHolderIsPrototype)),
469 GotoIf(WordEqual(handler_kind, IntPtrConstant(LoadHandler::kGlobal)),
472 GotoIf(WordEqual(handler_kind, IntPtrConstant(LoadHandler::kProxy)), &proxy);
474 Branch(WordEqual(handler_kind, IntPtrConstant(LoadHandler::kModuleExport)),
475 &module_export, &interceptor);
478 HandleLoadField(holder, handler_word, &var_double_value, &rebox_double,
483 if (on_nonexistent == OnNonExistent::kThrowReferenceError) {
484 exit_point->ReturnCallRuntime(Runtime::kThrowReferenceError, p->context,
487 DCHECK_EQ(OnNonExistent::kReturnUndefined, on_nonexistent);
488 exit_point->Return(UndefinedConstant());
493 Comment(
"constant_load");
494 TNode<IntPtrT> descriptor =
495 Signed(DecodeWord<LoadHandler::DescriptorBits>(handler_word));
496 Node* value = LoadDescriptorValue(LoadMap(holder), descriptor);
498 exit_point->Return(value);
503 Comment(
"load_normal");
504 TNode<NameDictionary> properties = CAST(LoadSlowProperties(holder));
505 TVARIABLE(IntPtrT, var_name_index);
506 Label found(
this, &var_name_index);
507 NameDictionaryLookup<NameDictionary>(properties, CAST(p->name), &found,
508 &var_name_index, miss);
511 VARIABLE(var_details, MachineRepresentation::kWord32);
512 VARIABLE(var_value, MachineRepresentation::kTagged);
513 LoadPropertyFromNameDictionary(properties, var_name_index.value(),
514 &var_details, &var_value);
515 Node* value = CallGetterIfAccessor(var_value.value(), var_details.value(),
516 p->context, p->receiver, miss);
517 exit_point->Return(value);
523 Comment(
"accessor_load");
524 TNode<IntPtrT> descriptor =
525 Signed(DecodeWord<LoadHandler::DescriptorBits>(handler_word));
526 Node* accessor_pair = LoadDescriptorValue(LoadMap(holder), descriptor);
527 CSA_ASSERT(
this, IsAccessorPair(accessor_pair));
528 Node* getter = LoadObjectField(accessor_pair, AccessorPair::kGetterOffset);
529 CSA_ASSERT(
this, Word32BinaryNot(IsTheHole(getter)));
531 Callable callable = CodeFactory::Call(isolate());
532 exit_point->Return(CallJS(callable, p->context, getter, p->receiver));
535 BIND(&native_data_property);
536 HandleLoadCallbackProperty(p, CAST(holder), handler_word, exit_point);
539 HandleLoadAccessor(p, CAST(holder), handler_word, CAST(handler), handler_kind,
544 VARIABLE(var_index, MachineType::PointerRepresentation());
545 VARIABLE(var_unique, MachineRepresentation::kTagged);
547 Label if_index(
this), if_unique_name(
this),
548 to_name_failed(
this, Label::kDeferred);
550 if (support_elements == kSupportElements) {
551 DCHECK_NE(on_nonexistent, OnNonExistent::kThrowReferenceError);
553 TryToName(p->name, &if_index, &var_index, &if_unique_name, &var_unique,
556 BIND(&if_unique_name);
557 exit_point->ReturnCallStub(
558 Builtins::CallableFor(isolate(), Builtins::kProxyGetProperty),
559 p->context, holder, var_unique.value(), p->receiver,
560 SmiConstant(on_nonexistent));
565 Goto(&to_name_failed);
567 BIND(&to_name_failed);
568 exit_point->ReturnCallRuntime(Runtime::kGetPropertyWithReceiver,
569 p->context, holder, p->name, p->receiver,
570 SmiConstant(on_nonexistent));
572 exit_point->ReturnCallStub(
573 Builtins::CallableFor(isolate(), Builtins::kProxyGetProperty),
574 p->context, holder, p->name, p->receiver,
575 SmiConstant(on_nonexistent));
581 CSA_ASSERT(
this, IsPropertyCell(holder));
583 Node* value = LoadObjectField(holder, PropertyCell::kValueOffset);
585 LoadAndUntagToWord32ObjectField(holder, PropertyCell::kDetailsOffset);
586 GotoIf(IsTheHole(value), miss);
589 CallGetterIfAccessor(value, details, p->context, p->receiver, miss));
594 Comment(
"load_interceptor");
595 exit_point->ReturnCallRuntime(Runtime::kLoadPropertyWithInterceptor,
596 p->context, p->name, p->receiver, holder,
600 BIND(&module_export);
602 Comment(
"module export");
603 Node* index = DecodeWord<LoadHandler::ExportsIndexBits>(handler_word);
605 LoadObjectField(p->receiver, JSModuleNamespace::kModuleOffset,
606 MachineType::TaggedPointer());
607 TNode<ObjectHashTable> exports = CAST(LoadObjectField(
608 module, Module::kExportsOffset, MachineType::TaggedPointer()));
609 Node* cell = LoadFixedArrayElement(exports, index);
611 CSA_ASSERT(
this, IsCell(cell));
612 Node* value = LoadCellValue(cell);
613 Label is_the_hole(
this, Label::kDeferred);
614 GotoIf(IsTheHole(value), &is_the_hole);
615 exit_point->Return(value);
619 Node* message = SmiConstant(MessageTemplate::kNotDefined);
620 exit_point->ReturnCallRuntime(Runtime::kThrowReferenceError, p->context,
626 exit_point->Return(AllocateHeapNumberWithValue(var_double_value.value()));
646 template <
typename ICHandler,
typename ICParameters>
647 Node* AccessorAssembler::HandleProtoHandler(
648 const ICParameters* p, Node* handler,
const OnCodeHandler& on_code_handler,
649 const OnFoundOnReceiver& on_found_on_receiver, Label* miss,
655 Node* maybe_validity_cell =
656 LoadObjectField(handler, ICHandler::kValidityCellOffset);
657 CheckPrototypeValidityCell(maybe_validity_cell, miss);
664 Node* smi_or_code_handler =
665 LoadObjectField(handler, ICHandler::kSmiHandlerOffset);
666 if (on_code_handler) {
667 Label if_smi_handler(
this);
668 GotoIf(TaggedIsSmi(smi_or_code_handler), &if_smi_handler);
670 CSA_ASSERT(
this, IsCodeMap(LoadMap(smi_or_code_handler)));
671 on_code_handler(smi_or_code_handler);
673 BIND(&if_smi_handler);
675 CSA_ASSERT(
this, TaggedIsSmi(smi_or_code_handler));
677 Node* handler_flags = SmiUntag(smi_or_code_handler);
683 int mask = ICHandler::LookupOnReceiverBits::kMask |
684 ICHandler::DoAccessCheckOnReceiverBits::kMask;
685 if (ic_mode == ICMode::kGlobalIC) {
686 CSA_ASSERT(
this, IsClearWord(handler_flags, mask));
688 DCHECK_EQ(ICMode::kNonGlobalIC, ic_mode);
690 Label done(
this), if_do_access_check(
this), if_lookup_on_receiver(
this);
691 GotoIf(IsClearWord(handler_flags, mask), &done);
694 WordNotEqual(WordAnd(handler_flags, IntPtrConstant(mask)),
695 IntPtrConstant(mask)));
696 Branch(IsSetWord<LoadHandler::DoAccessCheckOnReceiverBits>(handler_flags),
697 &if_do_access_check, &if_lookup_on_receiver);
699 BIND(&if_do_access_check);
701 TNode<MaybeObject> data2 = LoadHandlerDataField(handler, 2);
702 CSA_ASSERT(
this, IsWeakOrCleared(data2));
703 TNode<Object> expected_native_context =
704 GetHeapObjectAssumeWeak(data2, miss);
705 EmitAccessCheck(expected_native_context, p->context, p->receiver, &done,
712 BIND(&if_lookup_on_receiver);
714 DCHECK_EQ(ICMode::kNonGlobalIC, ic_mode);
715 CSA_ASSERT(
this, Word32BinaryNot(HasInstanceType(
716 p->receiver, JS_GLOBAL_OBJECT_TYPE)));
718 TNode<NameDictionary> properties =
719 CAST(LoadSlowProperties(p->receiver));
720 TVARIABLE(IntPtrT, var_name_index);
721 Label found(
this, &var_name_index);
722 NameDictionaryLookup<NameDictionary>(properties, CAST(p->name), &found,
723 &var_name_index, &done);
726 if (on_found_on_receiver) {
727 on_found_on_receiver(properties, var_name_index.value());
736 return smi_or_code_handler;
740 void AccessorAssembler::HandleLoadICProtoHandler(
741 const LoadICParameters* p, Node* handler, Variable* var_holder,
742 Variable* var_smi_handler, Label* if_smi_handler, Label* miss,
743 ExitPoint* exit_point, ICMode ic_mode) {
744 DCHECK_EQ(MachineRepresentation::kTagged, var_holder->rep());
745 DCHECK_EQ(MachineRepresentation::kTagged, var_smi_handler->rep());
747 Node* smi_handler = HandleProtoHandler<LoadHandler>(
752 [=](Node* properties, Node* name_index) {
753 VARIABLE(var_details, MachineRepresentation::kWord32);
754 VARIABLE(var_value, MachineRepresentation::kTagged);
755 LoadPropertyFromNameDictionary(properties, name_index, &var_details,
758 CallGetterIfAccessor(var_value.value(), var_details.value(),
759 p->context, p->receiver, miss);
760 exit_point->Return(value);
764 TNode<MaybeObject> maybe_holder = LoadHandlerDataField(handler, 1);
766 Label load_from_cached_holder(
this), done(
this);
768 Branch(IsStrongReferenceTo(maybe_holder, NullConstant()), &done,
769 &load_from_cached_holder);
771 BIND(&load_from_cached_holder);
776 CSA_ASSERT(
this, IsWeakOrCleared(maybe_holder));
777 Node* holder = GetHeapObjectAssumeWeak(maybe_holder, miss);
779 var_holder->Bind(holder);
785 var_smi_handler->Bind(smi_handler);
786 Goto(if_smi_handler);
790 void AccessorAssembler::EmitAccessCheck(Node* expected_native_context,
791 Node* context, Node* receiver,
792 Label* can_access, Label* miss) {
793 CSA_ASSERT(
this, IsNativeContext(expected_native_context));
795 Node* native_context = LoadNativeContext(context);
796 GotoIf(WordEqual(expected_native_context, native_context), can_access);
798 GotoIfNot(IsJSGlobalProxy(receiver), miss);
801 Node* expected_token = LoadContextElement(expected_native_context,
802 Context::SECURITY_TOKEN_INDEX);
803 Node* current_token =
804 LoadContextElement(native_context, Context::SECURITY_TOKEN_INDEX);
805 Branch(WordEqual(expected_token, current_token), can_access, miss);
808 void AccessorAssembler::JumpIfDataProperty(Node* details, Label* writable,
812 GotoIf(IsSetWord32(details, PropertyDetails::kAttributesReadOnlyMask),
815 CSA_ASSERT(
this, IsNotSetWord32(details,
816 PropertyDetails::kAttributesReadOnlyMask));
818 Node* kind = DecodeWord32<PropertyDetails::KindField>(details);
819 GotoIf(Word32Equal(kind, Int32Constant(kData)), writable);
823 void AccessorAssembler::HandleStoreICNativeDataProperty(
824 const StoreICParameters* p, Node* holder, Node* handler_word) {
825 Comment(
"native_data_property_store");
826 TNode<IntPtrT> descriptor =
827 Signed(DecodeWord<StoreHandler::DescriptorBits>(handler_word));
828 Node* accessor_info = LoadDescriptorValue(LoadMap(holder), descriptor);
829 CSA_CHECK(
this, IsAccessorInfo(accessor_info));
831 Node* language_mode = GetLanguageMode(p->vector, p->slot);
833 TailCallRuntime(Runtime::kStoreCallbackProperty, p->context, p->receiver,
834 holder, accessor_info, p->name, p->value, language_mode);
837 void AccessorAssembler::HandleStoreICHandlerCase(
838 const StoreICParameters* p, TNode<MaybeObject> handler, Label* miss,
839 ICMode ic_mode, ElementSupport support_elements) {
840 Label if_smi_handler(
this), if_nonsmi_handler(
this);
841 Label if_proto_handler(
this), if_element_handler(
this), call_handler(
this),
842 store_transition_or_global(
this);
844 Branch(TaggedIsSmi(handler), &if_smi_handler, &if_nonsmi_handler);
848 BIND(&if_smi_handler);
850 Node* holder = p->receiver;
851 Node* handler_word = SmiUntag(CAST(handler));
853 Label if_fast_smi(
this), if_proxy(
this);
855 STATIC_ASSERT(StoreHandler::kGlobalProxy + 1 == StoreHandler::kNormal);
856 STATIC_ASSERT(StoreHandler::kNormal + 1 == StoreHandler::kProxy);
857 STATIC_ASSERT(StoreHandler::kProxy + 1 == StoreHandler::kKindsNumber);
859 Node* handler_kind = DecodeWord<StoreHandler::KindBits>(handler_word);
860 GotoIf(IntPtrLessThan(handler_kind,
861 IntPtrConstant(StoreHandler::kGlobalProxy)),
863 GotoIf(WordEqual(handler_kind, IntPtrConstant(StoreHandler::kProxy)),
866 WordEqual(handler_kind, IntPtrConstant(StoreHandler::kNormal)));
867 TNode<NameDictionary> properties = CAST(LoadSlowProperties(holder));
869 TVARIABLE(IntPtrT, var_name_index);
870 Label dictionary_found(
this, &var_name_index);
871 NameDictionaryLookup<NameDictionary>(
872 properties, CAST(p->name), &dictionary_found, &var_name_index, miss);
873 BIND(&dictionary_found);
875 Node* details = LoadDetailsByKeyIndex<NameDictionary>(
876 properties, var_name_index.value());
878 const int kTypeAndReadOnlyMask = PropertyDetails::KindField::kMask |
879 PropertyDetails::kAttributesReadOnlyMask;
880 STATIC_ASSERT(kData == 0);
881 GotoIf(IsSetWord32(details, kTypeAndReadOnlyMask), miss);
883 StoreValueByKeyIndex<NameDictionary>(properties, var_name_index.value(),
890 Node* handler_kind = DecodeWord<StoreHandler::KindBits>(handler_word);
892 Label data(
this), accessor(
this), native_data_property(
this);
893 GotoIf(WordEqual(handler_kind, IntPtrConstant(StoreHandler::kAccessor)),
895 Branch(WordEqual(handler_kind,
896 IntPtrConstant(StoreHandler::kNativeDataProperty)),
897 &native_data_property, &data);
900 HandleStoreAccessor(p, holder, handler_word);
902 BIND(&native_data_property);
903 HandleStoreICNativeDataProperty(p, holder, handler_word);
907 HandleStoreICSmiHandlerCase(handler_word, holder, p->value, miss);
911 HandleStoreToProxy(p, holder, miss, support_elements);
914 BIND(&if_nonsmi_handler);
916 GotoIf(IsWeakOrCleared(handler), &store_transition_or_global);
917 TNode<HeapObject> strong_handler = CAST(handler);
918 TNode<Map> handler_map = LoadMap(strong_handler);
919 Branch(IsCodeMap(handler_map), &call_handler, &if_proto_handler);
921 BIND(&if_proto_handler);
923 HandleStoreICProtoHandler(p, CAST(strong_handler), miss, ic_mode,
930 TailCallStub(StoreWithVectorDescriptor{}, CAST(strong_handler),
931 CAST(p->context), p->receiver, p->name, p->value, p->slot,
936 BIND(&store_transition_or_global);
939 CSA_ASSERT(
this, IsWeakOrCleared(handler));
940 TNode<HeapObject> map_or_property_cell =
941 GetHeapObjectAssumeWeak(handler, miss);
943 Label store_global(
this), store_transition(
this);
944 Branch(IsMap(map_or_property_cell), &store_transition, &store_global);
948 TNode<PropertyCell> property_cell = CAST(map_or_property_cell);
949 ExitPoint direct_exit(
this);
950 StoreGlobalIC_PropertyCellCase(property_cell, p->value, &direct_exit,
953 BIND(&store_transition);
955 TNode<Map> map = CAST(map_or_property_cell);
956 HandleStoreICTransitionMapHandlerCase(p, map, miss,
957 kCheckPrototypeValidity);
963 void AccessorAssembler::HandleStoreICTransitionMapHandlerCase(
964 const StoreICParameters* p, TNode<Map> transition_map, Label* miss,
965 StoreTransitionMapFlags flags) {
966 DCHECK_EQ(0, flags & ~kStoreTransitionMapFlagsMask);
967 if (flags & kCheckPrototypeValidity) {
968 Node* maybe_validity_cell =
969 LoadObjectField(transition_map, Map::kPrototypeValidityCellOffset);
970 CheckPrototypeValidityCell(maybe_validity_cell, miss);
973 TNode<Uint32T> bitfield3 = LoadMapBitField3(transition_map);
974 CSA_ASSERT(
this, IsClearWord32<Map::IsDictionaryMapBit>(bitfield3));
975 GotoIf(IsSetWord32<Map::IsDeprecatedBit>(bitfield3), miss);
978 Node* nof = DecodeWordFromWord32<Map::NumberOfOwnDescriptorsBits>(bitfield3);
979 CSA_ASSERT(
this, WordNotEqual(nof, IntPtrConstant(0)));
980 TNode<DescriptorArray> descriptors = LoadMapDescriptors(transition_map);
982 Node* factor = IntPtrConstant(DescriptorArray::kEntrySize);
983 TNode<IntPtrT> last_key_index = UncheckedCast<IntPtrT>(IntPtrAdd(
984 IntPtrConstant(DescriptorArray::ToKeyIndex(-1)), IntPtrMul(nof, factor)));
985 if (flags & kValidateTransitionHandler) {
986 TNode<Name> key = LoadKeyByKeyIndex(descriptors, last_key_index);
987 GotoIf(WordNotEqual(key, p->name), miss);
989 CSA_ASSERT(
this, WordEqual(LoadKeyByKeyIndex(descriptors, last_key_index),
992 Node* details = LoadDetailsByKeyIndex(descriptors, last_key_index);
993 if (flags & kValidateTransitionHandler) {
997 Label attributes_ok(
this);
998 const int kKindAndAttributesDontDeleteReadOnlyMask =
999 PropertyDetails::KindField::kMask |
1000 PropertyDetails::kAttributesDontDeleteMask |
1001 PropertyDetails::kAttributesReadOnlyMask;
1002 STATIC_ASSERT(kData == 0);
1005 GotoIf(IsSetWord32(details, kKindAndAttributesDontDeleteReadOnlyMask),
1010 IsSetWord32(details, PropertyDetails::kAttributesDontEnumMask),
1011 IsPrivateSymbol(p->name)),
1012 &attributes_ok, miss);
1014 BIND(&attributes_ok);
1017 OverwriteExistingFastDataProperty(p->receiver, transition_map, descriptors,
1018 last_key_index, details, p->value, miss,
1022 void AccessorAssembler::CheckFieldType(TNode<DescriptorArray> descriptors,
1023 Node* name_index, Node* representation,
1024 Node* value, Label* bailout) {
1025 Label r_smi(
this), r_double(
this), r_heapobject(
this), all_fine(
this);
1029 GotoIf(Word32Equal(representation, Int32Constant(Representation::kSmi)),
1031 GotoIf(Word32Equal(representation, Int32Constant(Representation::kDouble)),
1034 Word32Equal(representation, Int32Constant(Representation::kHeapObject)),
1036 GotoIf(Word32Equal(representation, Int32Constant(Representation::kNone)),
1038 CSA_ASSERT(
this, Word32Equal(representation,
1039 Int32Constant(Representation::kTagged)));
1043 { Branch(TaggedIsSmi(value), &all_fine, bailout); }
1047 GotoIf(TaggedIsSmi(value), &all_fine);
1048 Node* value_map = LoadMap(value);
1051 CSA_ASSERT(
this, WordNotEqual(value_map,
1052 LoadRoot(RootIndex::kMutableHeapNumberMap)));
1053 Branch(IsHeapNumberMap(value_map), &all_fine, bailout);
1056 BIND(&r_heapobject);
1058 GotoIf(TaggedIsSmi(value), bailout);
1059 TNode<MaybeObject> field_type = LoadFieldTypeByKeyIndex(
1060 descriptors, UncheckedCast<IntPtrT>(name_index));
1061 const Address kNoneType = FieldType::None().ptr();
1062 const Address kAnyType = FieldType::Any().ptr();
1063 DCHECK_NE(static_cast<uint32_t>(kNoneType), kClearedWeakHeapObjectLower32);
1064 DCHECK_NE(static_cast<uint32_t>(kAnyType), kClearedWeakHeapObjectLower32);
1066 GotoIf(WordEqual(BitcastMaybeObjectToWord(field_type),
1067 IntPtrConstant(kNoneType)),
1070 GotoIf(WordEqual(BitcastMaybeObjectToWord(field_type),
1071 IntPtrConstant(kAnyType)),
1075 TNode<Map> field_type_map =
1076 CAST(GetHeapObjectAssumeWeak(field_type, bailout));
1078 Branch(WordEqual(LoadMap(value), field_type_map), &all_fine, bailout);
1084 void AccessorAssembler::OverwriteExistingFastDataProperty(
1085 Node*
object, Node* object_map, Node* descriptors,
1086 Node* descriptor_name_index, Node* details, Node* value, Label* slow,
1087 bool do_transitioning_store) {
1088 Label done(
this), if_field(
this), if_descriptor(
this);
1091 Word32Equal(DecodeWord32<PropertyDetails::KindField>(details),
1092 Int32Constant(kData)));
1094 Branch(Word32Equal(DecodeWord32<PropertyDetails::LocationField>(details),
1095 Int32Constant(kField)),
1096 &if_field, &if_descriptor);
1100 if (FLAG_track_constant_fields && !do_transitioning_store) {
1104 DecodeWord32<PropertyDetails::ConstnessField>(details),
1105 Int32Constant(static_cast<int32_t>(VariableMode::kConst))),
1109 Node* representation =
1110 DecodeWord32<PropertyDetails::RepresentationField>(details);
1112 CheckFieldType(CAST(descriptors), descriptor_name_index, representation,
1116 DecodeWordFromWord32<PropertyDetails::FieldIndexField>(details);
1117 field_index = IntPtrAdd(field_index,
1118 LoadMapInobjectPropertiesStartInWords(object_map));
1119 Node* instance_size_in_words = LoadMapInstanceSizeInWords(object_map);
1121 Label inobject(
this), backing_store(
this);
1122 Branch(UintPtrLessThan(field_index, instance_size_in_words), &inobject,
1127 Node* field_offset = TimesPointerSize(field_index);
1128 Label tagged_rep(
this), double_rep(
this);
1130 Word32Equal(representation, Int32Constant(Representation::kDouble)),
1131 &double_rep, &tagged_rep);
1134 Node* double_value = ChangeNumberToFloat64(value);
1135 if (FLAG_unbox_double_fields) {
1136 if (do_transitioning_store) {
1137 StoreMap(
object, object_map);
1139 StoreObjectFieldNoWriteBarrier(
object, field_offset, double_value,
1140 MachineRepresentation::kFloat64);
1142 if (do_transitioning_store) {
1143 Node* mutable_heap_number =
1144 AllocateMutableHeapNumberWithValue(double_value);
1145 StoreMap(
object, object_map);
1146 StoreObjectField(
object, field_offset, mutable_heap_number);
1148 Node* mutable_heap_number = LoadObjectField(
object, field_offset);
1149 StoreHeapNumberValue(mutable_heap_number, double_value);
1157 if (do_transitioning_store) {
1158 StoreMap(
object, object_map);
1160 StoreObjectField(
object, field_offset, value);
1165 BIND(&backing_store);
1167 Node* backing_store_index =
1168 IntPtrSub(field_index, instance_size_in_words);
1170 if (do_transitioning_store) {
1174 VARIABLE(var_value, MachineRepresentation::kTagged, value);
1177 GotoIf(Word32NotEqual(representation,
1178 Int32Constant(Representation::kDouble)),
1181 Node* double_value = ChangeNumberToFloat64(value);
1182 Node* mutable_heap_number =
1183 AllocateMutableHeapNumberWithValue(double_value);
1184 var_value.Bind(mutable_heap_number);
1190 TNode<PropertyArray> properties =
1191 CAST(ExtendPropertiesBackingStore(
object, backing_store_index));
1192 StorePropertyArrayElement(properties, backing_store_index,
1194 StoreMap(
object, object_map);
1198 Label tagged_rep(
this), double_rep(
this);
1199 TNode<PropertyArray> properties = CAST(LoadFastProperties(
object));
1201 Word32Equal(representation, Int32Constant(Representation::kDouble)),
1202 &double_rep, &tagged_rep);
1205 Node* mutable_heap_number =
1206 LoadPropertyArrayElement(properties, backing_store_index);
1207 Node* double_value = ChangeNumberToFloat64(value);
1208 StoreHeapNumberValue(mutable_heap_number, double_value);
1213 StorePropertyArrayElement(properties, backing_store_index, value);
1220 BIND(&if_descriptor);
1223 Node* constant = LoadValueByKeyIndex(
1224 CAST(descriptors), UncheckedCast<IntPtrT>(descriptor_name_index));
1225 GotoIf(WordNotEqual(value, constant), slow);
1227 if (do_transitioning_store) {
1228 StoreMap(
object, object_map);
1235 void AccessorAssembler::CheckPrototypeValidityCell(Node* maybe_validity_cell,
1238 GotoIf(WordEqual(maybe_validity_cell, SmiConstant(Map::kPrototypeChainValid)),
1240 CSA_ASSERT(
this, TaggedIsNotSmi(maybe_validity_cell));
1242 Node* cell_value = LoadObjectField(maybe_validity_cell, Cell::kValueOffset);
1243 Branch(WordEqual(cell_value, SmiConstant(Map::kPrototypeChainValid)), &done,
1249 void AccessorAssembler::HandleStoreAccessor(
const StoreICParameters* p,
1250 Node* holder, Node* handler_word) {
1251 Comment(
"accessor_store");
1252 TNode<IntPtrT> descriptor =
1253 Signed(DecodeWord<StoreHandler::DescriptorBits>(handler_word));
1254 Node* accessor_pair = LoadDescriptorValue(LoadMap(holder), descriptor);
1255 CSA_ASSERT(
this, IsAccessorPair(accessor_pair));
1256 Node* setter = LoadObjectField(accessor_pair, AccessorPair::kSetterOffset);
1257 CSA_ASSERT(
this, Word32BinaryNot(IsTheHole(setter)));
1259 Callable callable = CodeFactory::Call(isolate());
1260 Return(CallJS(callable, p->context, setter, p->receiver, p->value));
1263 void AccessorAssembler::HandleStoreICProtoHandler(
1264 const StoreICParameters* p, TNode<StoreHandler> handler, Label* miss,
1265 ICMode ic_mode, ElementSupport support_elements) {
1266 Comment(
"HandleStoreICProtoHandler");
1268 OnCodeHandler on_code_handler;
1269 if (support_elements == kSupportElements) {
1271 on_code_handler = [=](Node* code_handler) {
1273 Label if_element_store(
this), if_transitioning_element_store(
this);
1274 Branch(IsStoreHandler0Map(LoadMap(handler)), &if_element_store,
1275 &if_transitioning_element_store);
1276 BIND(&if_element_store);
1278 TailCallStub(StoreWithVectorDescriptor{}, code_handler, p->context,
1279 p->receiver, p->name, p->value, p->slot, p->vector);
1282 BIND(&if_transitioning_element_store);
1284 TNode<MaybeObject> maybe_transition_map =
1285 LoadHandlerDataField(handler, 1);
1286 TNode<Map> transition_map =
1287 CAST(GetHeapObjectAssumeWeak(maybe_transition_map, miss));
1289 GotoIf(IsDeprecatedMap(transition_map), miss);
1291 TailCallStub(StoreTransitionDescriptor{}, code_handler, p->context,
1292 p->receiver, p->name, transition_map, p->value, p->slot,
1298 Node* smi_handler = HandleProtoHandler<StoreHandler>(
1299 p, handler, on_code_handler,
1301 [=](Node* properties, Node* name_index) {
1303 LoadDetailsByKeyIndex<NameDictionary>(properties, name_index);
1305 const int kTypeAndReadOnlyMask =
1306 PropertyDetails::KindField::kMask |
1307 PropertyDetails::kAttributesReadOnlyMask;
1308 STATIC_ASSERT(kData == 0);
1309 GotoIf(IsSetWord32(details, kTypeAndReadOnlyMask), miss);
1311 StoreValueByKeyIndex<NameDictionary>(
1312 CAST(properties), UncheckedCast<IntPtrT>(name_index), p->value);
1318 Label if_add_normal(
this), if_store_global_proxy(
this), if_api_setter(
this),
1319 if_accessor(
this), if_native_data_property(
this);
1321 CSA_ASSERT(
this, TaggedIsSmi(smi_handler));
1322 Node* handler_word = SmiUntag(smi_handler);
1324 Node* handler_kind = DecodeWord<StoreHandler::KindBits>(handler_word);
1325 GotoIf(WordEqual(handler_kind, IntPtrConstant(StoreHandler::kNormal)),
1328 TNode<MaybeObject> maybe_holder = LoadHandlerDataField(handler, 1);
1329 CSA_ASSERT(
this, IsWeakOrCleared(maybe_holder));
1330 TNode<Object> holder = GetHeapObjectAssumeWeak(maybe_holder, miss);
1332 GotoIf(WordEqual(handler_kind, IntPtrConstant(StoreHandler::kGlobalProxy)),
1333 &if_store_global_proxy);
1335 GotoIf(WordEqual(handler_kind, IntPtrConstant(StoreHandler::kAccessor)),
1338 GotoIf(WordEqual(handler_kind,
1339 IntPtrConstant(StoreHandler::kNativeDataProperty)),
1340 &if_native_data_property);
1342 GotoIf(WordEqual(handler_kind, IntPtrConstant(StoreHandler::kApiSetter)),
1345 GotoIf(WordEqual(handler_kind,
1346 IntPtrConstant(StoreHandler::kApiSetterHolderIsPrototype)),
1350 WordEqual(handler_kind, IntPtrConstant(StoreHandler::kProxy)));
1351 HandleStoreToProxy(p, holder, miss, support_elements);
1353 BIND(&if_add_normal);
1360 TNode<Map> receiver_map = LoadMap(p->receiver);
1361 InvalidateValidityCellIfPrototype(receiver_map);
1363 TNode<NameDictionary> properties = CAST(LoadSlowProperties(p->receiver));
1364 Add<NameDictionary>(properties, CAST(p->name), p->value, &slow);
1368 TailCallRuntime(Runtime::kAddDictionaryProperty, p->context, p->receiver,
1373 HandleStoreAccessor(p, holder, handler_word);
1375 BIND(&if_native_data_property);
1376 HandleStoreICNativeDataProperty(p, holder, handler_word);
1378 BIND(&if_api_setter);
1380 Comment(
"api_setter");
1381 CSA_ASSERT(
this, TaggedIsNotSmi(handler));
1382 Node* call_handler_info = holder;
1386 TNode<MaybeObject> maybe_context = Select<MaybeObject>(
1387 IsSetWord<LoadHandler::DoAccessCheckOnReceiverBits>(handler_word),
1388 [=] {
return LoadHandlerDataField(handler, 3); },
1389 [=] {
return LoadHandlerDataField(handler, 2); });
1391 CSA_ASSERT(
this, IsWeakOrCleared(maybe_context));
1392 TNode<Object> context = Select<Object>(
1393 IsCleared(maybe_context), [=] {
return SmiConstant(0); },
1394 [=] {
return GetHeapObjectAssumeWeak(maybe_context); });
1396 Node* foreign = LoadObjectField(call_handler_info,
1397 CallHandlerInfo::kJsCallbackOffset);
1398 Node* callback = LoadObjectField(foreign, Foreign::kForeignAddressOffset,
1399 MachineType::Pointer());
1401 LoadObjectField(call_handler_info, CallHandlerInfo::kDataOffset);
1403 VARIABLE(api_holder, MachineRepresentation::kTagged, p->receiver);
1405 GotoIf(WordEqual(handler_kind, IntPtrConstant(StoreHandler::kApiSetter)),
1410 WordEqual(handler_kind,
1411 IntPtrConstant(StoreHandler::kApiSetterHolderIsPrototype)));
1413 api_holder.Bind(LoadMapPrototype(LoadMap(p->receiver)));
1417 Callable callable = CodeFactory::CallApiCallback(isolate(), 1);
1418 Return(CallStub(callable,
nullptr, context, data, api_holder.value(),
1419 callback, p->receiver, p->value));
1422 BIND(&if_store_global_proxy);
1424 ExitPoint direct_exit(
this);
1425 StoreGlobalIC_PropertyCellCase(holder, p->value, &direct_exit, miss);
1430 Node* AccessorAssembler::GetLanguageMode(Node* vector, Node* slot) {
1431 VARIABLE(var_language_mode, MachineRepresentation::kTaggedSigned,
1432 SmiConstant(LanguageMode::kStrict));
1433 Label language_mode_determined(
this);
1434 BranchIfStrictMode(vector, slot, &language_mode_determined);
1435 var_language_mode.Bind(SmiConstant(LanguageMode::kSloppy));
1436 Goto(&language_mode_determined);
1437 BIND(&language_mode_determined);
1438 return var_language_mode.value();
1441 void AccessorAssembler::HandleStoreToProxy(
const StoreICParameters* p,
1442 Node* proxy, Label* miss,
1443 ElementSupport support_elements) {
1444 VARIABLE(var_index, MachineType::PointerRepresentation());
1445 VARIABLE(var_unique, MachineRepresentation::kTagged);
1447 Label if_index(
this), if_unique_name(
this),
1448 to_name_failed(
this, Label::kDeferred);
1450 Node* language_mode = GetLanguageMode(p->vector, p->slot);
1452 if (support_elements == kSupportElements) {
1453 TryToName(p->name, &if_index, &var_index, &if_unique_name, &var_unique,
1456 BIND(&if_unique_name);
1457 CallBuiltin(Builtins::kProxySetProperty, p->context, proxy,
1458 var_unique.value(), p->value, p->receiver, language_mode);
1465 Goto(&to_name_failed);
1467 BIND(&to_name_failed);
1468 TailCallRuntime(Runtime::kSetPropertyWithReceiver, p->context, proxy,
1469 p->name, p->value, p->receiver, language_mode);
1471 Node* name = CallBuiltin(Builtins::kToName, p->context, p->name);
1472 TailCallBuiltin(Builtins::kProxySetProperty, p->context, proxy, name,
1473 p->value, p->receiver, language_mode);
1477 void AccessorAssembler::HandleStoreICSmiHandlerCase(Node* handler_word,
1478 Node* holder, Node* value,
1480 Comment(
"field store");
1482 Node* handler_kind = DecodeWord<StoreHandler::KindBits>(handler_word);
1483 if (FLAG_track_constant_fields) {
1486 Word32Or(WordEqual(handler_kind, IntPtrConstant(StoreHandler::kField)),
1487 WordEqual(handler_kind,
1488 IntPtrConstant(StoreHandler::kConstField))));
1491 WordEqual(handler_kind, IntPtrConstant(StoreHandler::kField)));
1495 Node* field_representation =
1496 DecodeWord<StoreHandler::FieldRepresentationBits>(handler_word);
1498 Label if_smi_field(
this), if_double_field(
this), if_heap_object_field(
this),
1499 if_tagged_field(
this);
1501 GotoIf(WordEqual(field_representation, IntPtrConstant(StoreHandler::kTagged)),
1503 GotoIf(WordEqual(field_representation,
1504 IntPtrConstant(StoreHandler::kHeapObject)),
1505 &if_heap_object_field);
1506 GotoIf(WordEqual(field_representation, IntPtrConstant(StoreHandler::kDouble)),
1508 CSA_ASSERT(
this, WordEqual(field_representation,
1509 IntPtrConstant(StoreHandler::kSmi)));
1510 Goto(&if_smi_field);
1512 BIND(&if_tagged_field);
1514 Comment(
"store tagged field");
1515 HandleStoreFieldAndReturn(handler_word, holder, Representation::Tagged(),
1519 BIND(&if_double_field);
1521 Comment(
"store double field");
1522 HandleStoreFieldAndReturn(handler_word, holder, Representation::Double(),
1526 BIND(&if_heap_object_field);
1528 Comment(
"store heap object field");
1529 HandleStoreFieldAndReturn(handler_word, holder,
1530 Representation::HeapObject(), value, miss);
1533 BIND(&if_smi_field);
1535 Comment(
"store smi field");
1536 HandleStoreFieldAndReturn(handler_word, holder, Representation::Smi(),
1541 void AccessorAssembler::HandleStoreFieldAndReturn(Node* handler_word,
1543 Representation representation,
1544 Node* value, Label* miss) {
1545 Node* prepared_value =
1546 PrepareValueForStore(handler_word, holder, representation, value, miss);
1548 Label if_inobject(
this), if_out_of_object(
this);
1549 Branch(IsSetWord<StoreHandler::IsInobjectBits>(handler_word), &if_inobject,
1554 StoreNamedField(handler_word, holder,
true, representation, prepared_value,
1559 BIND(&if_out_of_object);
1561 StoreNamedField(handler_word, holder,
false, representation, prepared_value,
1567 Node* AccessorAssembler::PrepareValueForStore(Node* handler_word, Node* holder,
1568 Representation representation,
1569 Node* value, Label* bailout) {
1570 if (representation.IsDouble()) {
1571 value = TryTaggedToFloat64(value, bailout);
1573 }
else if (representation.IsHeapObject()) {
1574 GotoIf(TaggedIsSmi(value), bailout);
1577 if (FLAG_track_constant_fields) {
1580 GotoIf(WordEqual(DecodeWord<StoreHandler::KindBits>(handler_word),
1581 IntPtrConstant(StoreHandler::kConstField)),
1584 TNode<IntPtrT> descriptor =
1585 Signed(DecodeWord<StoreHandler::DescriptorBits>(handler_word));
1586 TNode<MaybeObject> maybe_field_type =
1587 LoadDescriptorValueOrFieldType(LoadMap(holder), descriptor);
1589 GotoIf(TaggedIsSmi(maybe_field_type), &done);
1592 Node* field_type = GetHeapObjectAssumeWeak(maybe_field_type, bailout);
1593 Branch(WordEqual(LoadMap(value), field_type), &done, bailout);
1597 }
else if (representation.IsSmi()) {
1598 GotoIfNot(TaggedIsSmi(value), bailout);
1601 DCHECK(representation.IsTagged());
1606 Node* AccessorAssembler::ExtendPropertiesBackingStore(Node*
object,
1608 Comment(
"[ Extend storage");
1610 ParameterMode mode = OptimalParameterMode();
1614 VARIABLE(var_properties, MachineRepresentation::kTaggedPointer);
1615 VARIABLE(var_encoded_hash, MachineRepresentation::kWord32);
1616 VARIABLE(var_length, ParameterRepresentation(mode));
1618 Node* properties = LoadObjectField(
object, JSObject::kPropertiesOrHashOffset);
1619 var_properties.Bind(properties);
1621 Label if_smi_hash(
this), if_property_array(
this), extend_store(
this);
1622 Branch(TaggedIsSmi(properties), &if_smi_hash, &if_property_array);
1626 Node* hash = SmiToInt32(properties);
1627 Node* encoded_hash =
1628 Word32Shl(hash, Int32Constant(PropertyArray::HashField::kShift));
1629 var_encoded_hash.Bind(encoded_hash);
1630 var_length.Bind(IntPtrOrSmiConstant(0, mode));
1631 var_properties.Bind(EmptyFixedArrayConstant());
1632 Goto(&extend_store);
1635 BIND(&if_property_array);
1637 Node* length_and_hash_int32 = LoadAndUntagToWord32ObjectField(
1638 var_properties.value(), PropertyArray::kLengthAndHashOffset);
1639 var_encoded_hash.Bind(Word32And(
1640 length_and_hash_int32, Int32Constant(PropertyArray::HashField::kMask)));
1641 Node* length_intptr = ChangeInt32ToIntPtr(
1642 Word32And(length_and_hash_int32,
1643 Int32Constant(PropertyArray::LengthField::kMask)));
1644 Node* length = IntPtrToParameter(length_intptr, mode);
1645 var_length.Bind(length);
1646 Goto(&extend_store);
1649 BIND(&extend_store);
1651 VARIABLE(var_new_properties, MachineRepresentation::kTaggedPointer,
1652 var_properties.value());
1657 GotoIf(UintPtrLessThan(index, ParameterToIntPtr(var_length.value(), mode)),
1660 Node* delta = IntPtrOrSmiConstant(JSObject::kFieldsAdded, mode);
1661 Node* new_capacity = IntPtrOrSmiAdd(var_length.value(), delta, mode);
1664 DCHECK(kMaxNumberOfDescriptors + JSObject::kFieldsAdded <
1665 FixedArrayBase::GetMaxLengthForNewSpaceAllocation(PACKED_ELEMENTS));
1669 UintPtrOrSmiLessThan(
1671 IntPtrOrSmiConstant(
1672 kMaxNumberOfDescriptors + JSObject::kFieldsAdded, mode),
1675 Node* new_properties = AllocatePropertyArray(new_capacity, mode);
1676 var_new_properties.Bind(new_properties);
1678 FillPropertyArrayWithUndefined(new_properties, var_length.value(),
1679 new_capacity, mode);
1683 CopyPropertyArrayValues(var_properties.value(), new_properties,
1684 var_length.value(), SKIP_WRITE_BARRIER, mode,
1685 DestroySource::kYes);
1689 Node* new_capacity_int32 =
1690 TruncateIntPtrToInt32(ParameterToIntPtr(new_capacity, mode));
1691 Node* new_length_and_hash_int32 =
1692 Word32Or(var_encoded_hash.value(), new_capacity_int32);
1693 StoreObjectField(new_properties, PropertyArray::kLengthAndHashOffset,
1694 SmiFromInt32(new_length_and_hash_int32));
1695 StoreObjectField(
object, JSObject::kPropertiesOrHashOffset, new_properties);
1696 Comment(
"] Extend storage");
1699 return var_new_properties.value();
1703 void AccessorAssembler::StoreNamedField(Node* handler_word, Node*
object,
1705 Representation representation,
1706 Node* value, Label* bailout) {
1707 bool store_value_as_double = representation.IsDouble();
1708 Node* property_storage = object;
1710 property_storage = LoadFastProperties(
object);
1713 Node* index = DecodeWord<StoreHandler::FieldIndexBits>(handler_word);
1714 Node* offset = IntPtrMul(index, IntPtrConstant(kPointerSize));
1715 if (representation.IsDouble()) {
1716 if (!FLAG_unbox_double_fields || !is_inobject) {
1718 property_storage = LoadObjectField(property_storage, offset);
1720 offset = IntPtrConstant(HeapNumber::kValueOffset);
1725 if (FLAG_track_constant_fields) {
1727 GotoIfNot(WordEqual(DecodeWord<StoreHandler::KindBits>(handler_word),
1728 IntPtrConstant(StoreHandler::kConstField)),
1731 if (store_value_as_double) {
1732 Node* current_value =
1733 LoadObjectField(property_storage, offset, MachineType::Float64());
1734 GotoIfNot(Float64Equal(current_value, value), bailout);
1736 Node* current_value = LoadObjectField(property_storage, offset);
1737 GotoIfNot(WordEqual(current_value, value), bailout);
1745 if (store_value_as_double) {
1746 StoreObjectFieldNoWriteBarrier(property_storage, offset, value,
1747 MachineRepresentation::kFloat64);
1748 }
else if (representation.IsSmi()) {
1749 StoreObjectFieldNoWriteBarrier(property_storage, offset, value);
1751 StoreObjectField(property_storage, offset, value);
1755 void AccessorAssembler::EmitFastElementsBoundsCheck(Node*
object,
1758 Node* is_jsarray_condition,
1760 VARIABLE(var_length, MachineType::PointerRepresentation());
1761 Comment(
"Fast elements bounds check");
1762 Label if_array(
this), length_loaded(
this, &var_length);
1763 GotoIf(is_jsarray_condition, &if_array);
1765 var_length.Bind(SmiUntag(LoadFixedArrayBaseLength(elements)));
1766 Goto(&length_loaded);
1770 var_length.Bind(SmiUntag(LoadFastJSArrayLength(
object)));
1771 Goto(&length_loaded);
1773 BIND(&length_loaded);
1774 GotoIfNot(UintPtrLessThan(intptr_index, var_length.value()), miss);
1777 void AccessorAssembler::EmitElementLoad(
1778 Node*
object, Node* elements, Node* elements_kind,
1779 SloppyTNode<IntPtrT> intptr_index, Node* is_jsarray_condition,
1780 Label* if_hole, Label* rebox_double, Variable* var_double_value,
1781 Label* unimplemented_elements_kind, Label* out_of_bounds, Label* miss,
1782 ExitPoint* exit_point) {
1783 Label if_typed_array(
this), if_fast_packed(
this), if_fast_holey(
this),
1784 if_fast_double(
this), if_fast_holey_double(
this), if_nonfast(
this),
1785 if_dictionary(
this);
1787 Int32GreaterThan(elements_kind, Int32Constant(LAST_FAST_ELEMENTS_KIND)),
1790 EmitFastElementsBoundsCheck(
object, elements, intptr_index,
1791 is_jsarray_condition, out_of_bounds);
1793 PACKED_SMI_ELEMENTS, PACKED_ELEMENTS,
1795 HOLEY_SMI_ELEMENTS, HOLEY_ELEMENTS,
1797 PACKED_DOUBLE_ELEMENTS,
1799 HOLEY_DOUBLE_ELEMENTS};
1801 &if_fast_packed, &if_fast_packed,
1803 &if_fast_holey, &if_fast_holey,
1807 &if_fast_holey_double};
1808 Switch(elements_kind, unimplemented_elements_kind, kinds, labels,
1811 BIND(&if_fast_packed);
1813 Comment(
"fast packed elements");
1814 exit_point->Return(LoadFixedArrayElement(CAST(elements), intptr_index));
1817 BIND(&if_fast_holey);
1819 Comment(
"fast holey elements");
1820 Node* element = LoadFixedArrayElement(CAST(elements), intptr_index);
1821 GotoIf(WordEqual(element, TheHoleConstant()), if_hole);
1822 exit_point->Return(element);
1825 BIND(&if_fast_double);
1827 Comment(
"packed double elements");
1828 var_double_value->Bind(LoadFixedDoubleArrayElement(elements, intptr_index,
1829 MachineType::Float64()));
1833 BIND(&if_fast_holey_double);
1835 Comment(
"holey double elements");
1836 Node* value = LoadFixedDoubleArrayElement(elements, intptr_index,
1837 MachineType::Float64(), 0,
1838 INTPTR_PARAMETERS, if_hole);
1839 var_double_value->Bind(value);
1845 STATIC_ASSERT(LAST_ELEMENTS_KIND == LAST_FIXED_TYPED_ARRAY_ELEMENTS_KIND);
1846 GotoIf(Int32GreaterThanOrEqual(
1848 Int32Constant(FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND)),
1850 GotoIf(Word32Equal(elements_kind, Int32Constant(DICTIONARY_ELEMENTS)),
1852 Goto(unimplemented_elements_kind);
1855 BIND(&if_dictionary);
1857 Comment(
"dictionary elements");
1858 GotoIf(IntPtrLessThan(intptr_index, IntPtrConstant(0)), out_of_bounds);
1860 TNode<Object> value = BasicLoadNumberDictionaryElement(
1861 CAST(elements), intptr_index, miss, if_hole);
1862 exit_point->Return(value);
1865 BIND(&if_typed_array);
1867 Comment(
"typed elements");
1869 Node* buffer = LoadObjectField(
object, JSArrayBufferView::kBufferOffset);
1870 GotoIf(IsDetachedBuffer(buffer), miss);
1873 Node* length = SmiUntag(LoadJSTypedArrayLength(CAST(
object)));
1874 GotoIfNot(UintPtrLessThan(intptr_index, length), out_of_bounds);
1876 Node* backing_store = LoadFixedTypedArrayBackingStore(CAST(elements));
1878 Label uint8_elements(
this), int8_elements(
this), uint16_elements(
this),
1879 int16_elements(
this), uint32_elements(
this), int32_elements(
this),
1880 float32_elements(
this), float64_elements(
this), bigint64_elements(
this),
1881 biguint64_elements(
this);
1882 Label* elements_kind_labels[] = {
1883 &uint8_elements, &uint8_elements, &int8_elements,
1884 &uint16_elements, &int16_elements, &uint32_elements,
1885 &int32_elements, &float32_elements, &float64_elements,
1886 &bigint64_elements, &biguint64_elements};
1887 int32_t elements_kinds[] = {
1888 UINT8_ELEMENTS, UINT8_CLAMPED_ELEMENTS, INT8_ELEMENTS,
1889 UINT16_ELEMENTS, INT16_ELEMENTS, UINT32_ELEMENTS,
1890 INT32_ELEMENTS, FLOAT32_ELEMENTS, FLOAT64_ELEMENTS,
1891 BIGINT64_ELEMENTS, BIGUINT64_ELEMENTS};
1892 const size_t kTypedElementsKindCount =
1893 LAST_FIXED_TYPED_ARRAY_ELEMENTS_KIND -
1894 FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND + 1;
1895 DCHECK_EQ(kTypedElementsKindCount, arraysize(elements_kinds));
1896 DCHECK_EQ(kTypedElementsKindCount, arraysize(elements_kind_labels));
1897 Switch(elements_kind, miss, elements_kinds, elements_kind_labels,
1898 kTypedElementsKindCount);
1899 BIND(&uint8_elements);
1901 Comment(
"UINT8_ELEMENTS");
1902 Node* element = Load(MachineType::Uint8(), backing_store, intptr_index);
1903 exit_point->Return(SmiFromInt32(element));
1905 BIND(&int8_elements);
1907 Comment(
"INT8_ELEMENTS");
1908 Node* element = Load(MachineType::Int8(), backing_store, intptr_index);
1909 exit_point->Return(SmiFromInt32(element));
1911 BIND(&uint16_elements);
1913 Comment(
"UINT16_ELEMENTS");
1914 Node* index = WordShl(intptr_index, IntPtrConstant(1));
1915 Node* element = Load(MachineType::Uint16(), backing_store, index);
1916 exit_point->Return(SmiFromInt32(element));
1918 BIND(&int16_elements);
1920 Comment(
"INT16_ELEMENTS");
1921 Node* index = WordShl(intptr_index, IntPtrConstant(1));
1922 Node* element = Load(MachineType::Int16(), backing_store, index);
1923 exit_point->Return(SmiFromInt32(element));
1925 BIND(&uint32_elements);
1927 Comment(
"UINT32_ELEMENTS");
1928 Node* index = WordShl(intptr_index, IntPtrConstant(2));
1929 Node* element = Load(MachineType::Uint32(), backing_store, index);
1930 exit_point->Return(ChangeUint32ToTagged(element));
1932 BIND(&int32_elements);
1934 Comment(
"INT32_ELEMENTS");
1935 Node* index = WordShl(intptr_index, IntPtrConstant(2));
1936 Node* element = Load(MachineType::Int32(), backing_store, index);
1937 exit_point->Return(ChangeInt32ToTagged(element));
1939 BIND(&float32_elements);
1941 Comment(
"FLOAT32_ELEMENTS");
1942 Node* index = WordShl(intptr_index, IntPtrConstant(2));
1943 Node* element = Load(MachineType::Float32(), backing_store, index);
1944 var_double_value->Bind(ChangeFloat32ToFloat64(element));
1947 BIND(&float64_elements);
1949 Comment(
"FLOAT64_ELEMENTS");
1950 Node* index = WordShl(intptr_index, IntPtrConstant(3));
1951 Node* element = Load(MachineType::Float64(), backing_store, index);
1952 var_double_value->Bind(element);
1955 BIND(&bigint64_elements);
1957 Comment(
"BIGINT64_ELEMENTS");
1958 exit_point->Return(LoadFixedTypedArrayElementAsTagged(
1959 backing_store, intptr_index, BIGINT64_ELEMENTS, INTPTR_PARAMETERS));
1961 BIND(&biguint64_elements);
1963 Comment(
"BIGUINT64_ELEMENTS");
1964 exit_point->Return(LoadFixedTypedArrayElementAsTagged(
1965 backing_store, intptr_index, BIGUINT64_ELEMENTS, INTPTR_PARAMETERS));
1970 void AccessorAssembler::NameDictionaryNegativeLookup(Node*
object,
1971 SloppyTNode<Name> name,
1973 CSA_ASSERT(
this, IsDictionaryMap(LoadMap(
object)));
1974 TNode<NameDictionary> properties = CAST(LoadSlowProperties(
object));
1976 TVARIABLE(IntPtrT, var_name_index);
1978 NameDictionaryLookup<NameDictionary>(properties, name, miss, &var_name_index,
1983 void AccessorAssembler::BranchIfStrictMode(Node* vector, Node* slot,
1986 LoadObjectField(vector, FeedbackVector::kSharedFunctionInfoOffset);
1987 TNode<FeedbackMetadata> metadata = CAST(LoadObjectField(
1988 sfi, SharedFunctionInfo::kOuterScopeInfoOrFeedbackMetadataOffset));
1989 Node* slot_int = SmiToInt32(slot);
1992 const int kItemsPerWord = FeedbackMetadata::VectorICComputer::kItemsPerWord;
1993 Node* word_index = Int32Div(slot_int, Int32Constant(kItemsPerWord));
1994 Node* word_offset = Int32Mod(slot_int, Int32Constant(kItemsPerWord));
1996 int32_t first_item = FeedbackMetadata::kHeaderSize - kHeapObjectTag;
1998 ElementOffsetFromIndex(ChangeInt32ToIntPtr(word_index), UINT32_ELEMENTS,
1999 INTPTR_PARAMETERS, first_item);
2001 Node* data = Load(MachineType::Int32(), metadata, offset);
2004 const int kBitsPerItem = FeedbackMetadata::kFeedbackSlotKindBits;
2005 Node* shift = Int32Mul(word_offset, Int32Constant(kBitsPerItem));
2006 const int kMask = FeedbackMetadata::VectorICComputer::kMask;
2007 Node* kind = Word32And(Word32Shr(data, shift), Int32Constant(kMask));
2009 STATIC_ASSERT(FeedbackSlotKind::kStoreGlobalSloppy <=
2010 FeedbackSlotKind::kLastSloppyKind);
2011 STATIC_ASSERT(FeedbackSlotKind::kStoreKeyedSloppy <=
2012 FeedbackSlotKind::kLastSloppyKind);
2013 STATIC_ASSERT(FeedbackSlotKind::kStoreNamedSloppy <=
2014 FeedbackSlotKind::kLastSloppyKind);
2015 GotoIfNot(Int32LessThanOrEqual(kind, Int32Constant(static_cast<int>(
2016 FeedbackSlotKind::kLastSloppyKind))),
2020 void AccessorAssembler::InvalidateValidityCellIfPrototype(Node* map,
2022 Label is_prototype(
this), cont(
this);
2023 if (bitfield2 ==
nullptr) {
2024 bitfield2 = LoadMapBitField2(map);
2027 Branch(IsSetWord32(bitfield2, Map::IsPrototypeMapBit::kMask), &is_prototype,
2030 BIND(&is_prototype);
2032 Node* maybe_prototype_info =
2033 LoadObjectField(map, Map::kTransitionsOrPrototypeInfoOffset);
2035 GotoIf(TaggedIsSmi(maybe_prototype_info), &cont);
2037 Node*
function = ExternalConstant(
2038 ExternalReference::invalidate_prototype_chains_function());
2039 CallCFunction1(MachineType::AnyTagged(), MachineType::AnyTagged(),
function,
2046 void AccessorAssembler::GenericElementLoad(Node* receiver, Node* receiver_map,
2047 SloppyTNode<Int32T> instance_type,
2048 Node* index, Label* slow) {
2049 Comment(
"integer index");
2051 ExitPoint direct_exit(
this);
2053 Label if_custom(
this), if_element_hole(
this), if_oob(
this);
2056 GotoIf(IsCustomElementsReceiverInstanceType(instance_type), &if_custom);
2057 Node* elements = LoadElements(receiver);
2058 Node* elements_kind = LoadMapElementsKind(receiver_map);
2059 Node* is_jsarray_condition = InstanceTypeEqual(instance_type, JS_ARRAY_TYPE);
2060 VARIABLE(var_double_value, MachineRepresentation::kFloat64);
2061 Label rebox_double(
this, &var_double_value);
2064 Label* unimplemented_elements_kind = slow;
2065 IncrementCounter(isolate()->counters()->ic_keyed_load_generic_smi(), 1);
2066 EmitElementLoad(receiver, elements, elements_kind, index,
2067 is_jsarray_condition, &if_element_hole, &rebox_double,
2068 &var_double_value, unimplemented_elements_kind, &if_oob, slow,
2071 BIND(&rebox_double);
2072 Return(AllocateHeapNumberWithValue(var_double_value.value()));
2076 Comment(
"out of bounds");
2078 GotoIf(IntPtrGreaterThanOrEqual(index, IntPtrConstant(0)),
2081 GotoIfNot(InstanceTypeEqual(instance_type, JS_TYPED_ARRAY_TYPE), slow);
2082 Return(UndefinedConstant());
2085 BIND(&if_element_hole);
2087 Comment(
"found the hole");
2088 Label return_undefined(
this);
2089 BranchIfPrototypesHaveNoElements(receiver_map, &return_undefined, slow);
2091 BIND(&return_undefined);
2092 Return(UndefinedConstant());
2097 Comment(
"check if string");
2098 GotoIfNot(IsStringInstanceType(instance_type), slow);
2099 Comment(
"load string character");
2100 TNode<IntPtrT> length = LoadStringLengthAsWord(receiver);
2101 GotoIfNot(UintPtrLessThan(index, length), slow);
2102 IncrementCounter(isolate()->counters()->ic_keyed_load_generic_smi(), 1);
2103 TailCallBuiltin(Builtins::kStringCharAt, NoContextConstant(), receiver,
2108 void AccessorAssembler::GenericPropertyLoad(Node* receiver, Node* receiver_map,
2109 SloppyTNode<Int32T> instance_type,
2110 const LoadICParameters* p,
2112 UseStubCache use_stub_cache) {
2113 ExitPoint direct_exit(
this);
2115 Comment(
"key is unique name");
2116 Label if_found_on_receiver(
this), if_property_dictionary(
this),
2117 lookup_prototype_chain(
this), special_receiver(
this);
2118 VARIABLE(var_details, MachineRepresentation::kWord32);
2119 VARIABLE(var_value, MachineRepresentation::kTagged);
2123 GotoIf(IsSpecialReceiverInstanceType(instance_type), &special_receiver);
2126 Node* bitfield3 = LoadMapBitField3(receiver_map);
2127 GotoIf(IsSetWord32<Map::IsDictionaryMapBit>(bitfield3),
2128 &if_property_dictionary);
2132 TNode<DescriptorArray> descriptors = LoadMapDescriptors(receiver_map);
2134 Label if_descriptor_found(
this), stub_cache(
this);
2135 TVARIABLE(IntPtrT, var_name_index);
2137 use_stub_cache == kUseStubCache ? &stub_cache : &lookup_prototype_chain;
2138 DescriptorLookup(p->name, descriptors, bitfield3, &if_descriptor_found,
2139 &var_name_index, notfound);
2141 BIND(&if_descriptor_found);
2143 LoadPropertyFromFastObject(receiver, receiver_map, descriptors,
2144 var_name_index.value(), &var_details,
2146 Goto(&if_found_on_receiver);
2149 if (use_stub_cache == kUseStubCache) {
2151 Comment(
"stub cache probe for fast property load");
2152 TVARIABLE(MaybeObject, var_handler);
2153 Label found_handler(
this, &var_handler), stub_cache_miss(
this);
2154 TryProbeStubCache(isolate()->load_stub_cache(), receiver, p->name,
2155 &found_handler, &var_handler, &stub_cache_miss);
2156 BIND(&found_handler);
2158 HandleLoadICHandlerCase(p, CAST(var_handler.value()), &stub_cache_miss,
2162 BIND(&stub_cache_miss);
2166 Comment(
"KeyedLoadGeneric_miss");
2167 TailCallRuntime(Runtime::kKeyedLoadIC_Miss, p->context, p->receiver,
2168 p->name, p->slot, p->vector);
2172 BIND(&if_property_dictionary);
2174 Comment(
"dictionary property load");
2178 TVARIABLE(IntPtrT, var_name_index);
2179 Label dictionary_found(
this, &var_name_index);
2180 TNode<NameDictionary> properties = CAST(LoadSlowProperties(receiver));
2181 NameDictionaryLookup<NameDictionary>(properties, CAST(p->name),
2182 &dictionary_found, &var_name_index,
2183 &lookup_prototype_chain);
2184 BIND(&dictionary_found);
2186 LoadPropertyFromNameDictionary(properties, var_name_index.value(),
2187 &var_details, &var_value);
2188 Goto(&if_found_on_receiver);
2192 BIND(&if_found_on_receiver);
2194 Node* value = CallGetterIfAccessor(var_value.value(), var_details.value(),
2195 p->context, receiver, slow);
2196 IncrementCounter(isolate()->counters()->ic_keyed_load_generic_symbol(), 1);
2200 BIND(&lookup_prototype_chain);
2202 VARIABLE(var_holder_map, MachineRepresentation::kTagged);
2203 VARIABLE(var_holder_instance_type, MachineRepresentation::kWord32);
2204 Label return_undefined(
this);
2205 Variable* merged_variables[] = {&var_holder_map, &var_holder_instance_type};
2206 Label loop(
this, arraysize(merged_variables), merged_variables);
2208 var_holder_map.Bind(receiver_map);
2209 var_holder_instance_type.Bind(instance_type);
2211 GotoIf(IsPrivateSymbol(p->name), &return_undefined);
2216 GotoIf(InstanceTypeEqual(var_holder_instance_type.value(),
2217 JS_TYPED_ARRAY_TYPE),
2219 Node* proto = LoadMapPrototype(var_holder_map.value());
2220 GotoIf(WordEqual(proto, NullConstant()), &return_undefined);
2221 Node* proto_map = LoadMap(proto);
2222 Node* proto_instance_type = LoadMapInstanceType(proto_map);
2223 var_holder_map.Bind(proto_map);
2224 var_holder_instance_type.Bind(proto_instance_type);
2225 Label next_proto(
this), return_value(
this, &var_value), goto_slow(
this);
2226 TryGetOwnProperty(p->context, receiver, proto, proto_map,
2227 proto_instance_type, p->name, &return_value, &var_value,
2228 &next_proto, &goto_slow);
2238 BIND(&return_value);
2239 Return(var_value.value());
2242 BIND(&return_undefined);
2243 Return(UndefinedConstant());
2246 BIND(&special_receiver);
2249 GotoIfNot(InstanceTypeEqual(instance_type, JS_PROXY_TYPE), slow);
2252 GotoIf(IsPrivateSymbol(p->name), slow);
2254 direct_exit.ReturnCallStub(
2255 Builtins::CallableFor(isolate(), Builtins::kProxyGetProperty),
2256 p->context, receiver , p->name,
2257 receiver, SmiConstant(OnNonExistent::kReturnUndefined));
2263 enum AccessorAssembler::StubCacheTable :
int {
2264 kPrimary =
static_cast<int>(StubCache::kPrimary),
2265 kSecondary = static_cast<int>(StubCache::kSecondary)
2268 Node* AccessorAssembler::StubCachePrimaryOffset(Node* name, Node* map) {
2270 STATIC_ASSERT(StubCache::kCacheIndexShift == Name::kHashShift);
2272 Node* hash_field = LoadNameHashField(name);
2274 Word32Equal(Word32And(hash_field,
2275 Int32Constant(Name::kHashNotComputedMask)),
2281 Node* map32 = TruncateIntPtrToInt32(BitcastTaggedToWord(map));
2283 Node* hash = Int32Add(hash_field, map32);
2284 uint32_t mask = (StubCache::kPrimaryTableSize - 1)
2285 << StubCache::kCacheIndexShift;
2286 return ChangeUint32ToWord(Word32And(hash, Int32Constant(mask)));
2289 Node* AccessorAssembler::StubCacheSecondaryOffset(Node* name, Node* seed) {
2293 Node* name32 = TruncateIntPtrToInt32(BitcastTaggedToWord(name));
2294 Node* hash = Int32Sub(TruncateIntPtrToInt32(seed), name32);
2295 hash = Int32Add(hash, Int32Constant(StubCache::kSecondaryMagic));
2296 int32_t mask = (StubCache::kSecondaryTableSize - 1)
2297 << StubCache::kCacheIndexShift;
2298 return ChangeUint32ToWord(Word32And(hash, Int32Constant(mask)));
2301 void AccessorAssembler::TryProbeStubCacheTable(
2302 StubCache* stub_cache, StubCacheTable table_id, Node* entry_offset,
2303 Node* name, Node* map, Label* if_handler,
2304 TVariable<MaybeObject>* var_handler, Label* if_miss) {
2305 StubCache::Table table =
static_cast<StubCache::Table
>(table_id);
2307 if (FLAG_test_secondary_stub_cache && table == StubCache::kPrimary) {
2310 }
else if (FLAG_test_primary_stub_cache && table == StubCache::kSecondary) {
2317 const int kMultiplier =
sizeof(StubCache::Entry) >> Name::kHashShift;
2318 entry_offset = IntPtrMul(entry_offset, IntPtrConstant(kMultiplier));
2321 Node* key_base = ExternalConstant(
2322 ExternalReference::Create(stub_cache->key_reference(table)));
2323 Node* entry_key = Load(MachineType::Pointer(), key_base, entry_offset);
2324 GotoIf(WordNotEqual(name, entry_key), if_miss);
2327 DCHECK_EQ(kPointerSize * 2, stub_cache->map_reference(table).address() -
2328 stub_cache->key_reference(table).address());
2330 Load(MachineType::Pointer(), key_base,
2331 IntPtrAdd(entry_offset, IntPtrConstant(kPointerSize * 2)));
2332 GotoIf(WordNotEqual(map, entry_map), if_miss);
2334 DCHECK_EQ(kPointerSize, stub_cache->value_reference(table).address() -
2335 stub_cache->key_reference(table).address());
2336 TNode<MaybeObject> handler = ReinterpretCast<MaybeObject>(
2337 Load(MachineType::AnyTagged(), key_base,
2338 IntPtrAdd(entry_offset, IntPtrConstant(kPointerSize))));
2341 *var_handler = handler;
2345 void AccessorAssembler::TryProbeStubCache(StubCache* stub_cache, Node* receiver,
2346 Node* name, Label* if_handler,
2347 TVariable<MaybeObject>* var_handler,
2349 Label try_secondary(
this), miss(
this);
2351 Counters* counters = isolate()->counters();
2352 IncrementCounter(counters->megamorphic_stub_cache_probes(), 1);
2355 GotoIf(TaggedIsSmi(receiver), &miss);
2357 Node* receiver_map = LoadMap(receiver);
2360 Node* primary_offset = StubCachePrimaryOffset(name, receiver_map);
2361 TryProbeStubCacheTable(stub_cache, kPrimary, primary_offset, name,
2362 receiver_map, if_handler, var_handler, &try_secondary);
2364 BIND(&try_secondary);
2367 Node* secondary_offset = StubCacheSecondaryOffset(name, primary_offset);
2368 TryProbeStubCacheTable(stub_cache, kSecondary, secondary_offset, name,
2369 receiver_map, if_handler, var_handler, &miss);
2374 IncrementCounter(counters->megamorphic_stub_cache_misses(), 1);
2381 void AccessorAssembler::LoadIC_BytecodeHandler(
const LoadICParameters* p,
2382 ExitPoint* exit_point) {
2392 Label stub_call(
this, Label::kDeferred), miss(
this, Label::kDeferred);
2396 Comment(
"LoadIC_BytecodeHandler_fast");
2398 Node* recv_map = LoadReceiverMap(p->receiver);
2399 GotoIf(IsDeprecatedMap(recv_map), &miss);
2401 TVARIABLE(MaybeObject, var_handler);
2402 Label try_polymorphic(
this), if_handler(
this, &var_handler);
2404 TNode<MaybeObject> feedback =
2405 TryMonomorphicCase(p->slot, p->vector, recv_map, &if_handler,
2406 &var_handler, &try_polymorphic);
2409 HandleLoadICHandlerCase(p, CAST(var_handler.value()), &miss, exit_point);
2411 BIND(&try_polymorphic);
2413 TNode<HeapObject> strong_feedback =
2414 GetHeapObjectIfStrong(feedback, &miss);
2415 GotoIfNot(IsWeakFixedArrayMap(LoadMap(strong_feedback)), &stub_call);
2416 HandlePolymorphicCase(recv_map, CAST(strong_feedback), &if_handler,
2417 &var_handler, &miss, 2);
2423 Comment(
"LoadIC_BytecodeHandler_noninlined");
2427 Builtins::CallableFor(isolate(), Builtins::kLoadIC_Noninlined);
2428 Node* code_target = HeapConstant(ic.code());
2429 exit_point->ReturnCallStub(ic.descriptor(), code_target, p->context,
2430 p->receiver, p->name, p->slot, p->vector);
2435 Comment(
"LoadIC_BytecodeHandler_miss");
2437 exit_point->ReturnCallRuntime(Runtime::kLoadIC_Miss, p->context,
2438 p->receiver, p->name, p->slot, p->vector);
2442 void AccessorAssembler::LoadIC(
const LoadICParameters* p) {
2445 ExitPoint direct_exit(
this);
2447 TVARIABLE(MaybeObject, var_handler);
2448 Label if_handler(
this, &var_handler), non_inlined(
this, Label::kDeferred),
2449 try_polymorphic(
this), miss(
this, Label::kDeferred);
2451 Node* receiver_map = LoadReceiverMap(p->receiver);
2452 GotoIf(IsDeprecatedMap(receiver_map), &miss);
2455 TNode<MaybeObject> feedback =
2456 TryMonomorphicCase(p->slot, p->vector, receiver_map, &if_handler,
2457 &var_handler, &try_polymorphic);
2459 HandleLoadICHandlerCase(p, CAST(var_handler.value()), &miss, &direct_exit);
2461 BIND(&try_polymorphic);
2462 TNode<HeapObject> strong_feedback = GetHeapObjectIfStrong(feedback, &miss);
2465 Comment(
"LoadIC_try_polymorphic");
2466 GotoIfNot(IsWeakFixedArrayMap(LoadMap(strong_feedback)), &non_inlined);
2467 HandlePolymorphicCase(receiver_map, CAST(strong_feedback), &if_handler,
2468 &var_handler, &miss, 2);
2473 LoadIC_Noninlined(p, receiver_map, strong_feedback, &var_handler,
2474 &if_handler, &miss, &direct_exit);
2478 direct_exit.ReturnCallRuntime(Runtime::kLoadIC_Miss, p->context, p->receiver,
2479 p->name, p->slot, p->vector);
2482 void AccessorAssembler::LoadIC_Noninlined(
const LoadICParameters* p,
2484 TNode<HeapObject> feedback,
2485 TVariable<MaybeObject>* var_handler,
2486 Label* if_handler, Label* miss,
2487 ExitPoint* exit_point) {
2488 Label try_uninitialized(
this, Label::kDeferred);
2492 CSA_ASSERT(
this, Word32BinaryNot(IsDeprecatedMap(receiver_map)));
2493 CSA_ASSERT(
this, WordNotEqual(receiver_map, feedback));
2494 CSA_ASSERT(
this, Word32BinaryNot(IsWeakFixedArrayMap(LoadMap(feedback))));
2495 DCHECK_EQ(MachineRepresentation::kTagged, var_handler->rep());
2499 GotoIfNot(WordEqual(feedback, LoadRoot(RootIndex::kmegamorphic_symbol)),
2500 &try_uninitialized);
2502 TryProbeStubCache(isolate()->load_stub_cache(), p->receiver, p->name,
2503 if_handler, var_handler, miss);
2506 BIND(&try_uninitialized);
2509 GotoIfNot(WordEqual(feedback, LoadRoot(RootIndex::kuninitialized_symbol)),
2511 exit_point->ReturnCallStub(
2512 Builtins::CallableFor(isolate(), Builtins::kLoadIC_Uninitialized),
2513 p->context, p->receiver, p->name, p->slot, p->vector);
2517 void AccessorAssembler::LoadIC_Uninitialized(
const LoadICParameters* p) {
2518 Label miss(
this, Label::kDeferred);
2519 Node* receiver = p->receiver;
2520 GotoIf(TaggedIsSmi(receiver), &miss);
2521 Node* receiver_map = LoadMap(receiver);
2522 Node* instance_type = LoadMapInstanceType(receiver_map);
2525 StoreFeedbackVectorSlot(p->vector, p->slot,
2526 LoadRoot(RootIndex::kpremonomorphic_symbol),
2527 SKIP_WRITE_BARRIER, 0, SMI_PARAMETERS);
2528 StoreWeakReferenceInFeedbackVector(p->vector, p->slot, receiver_map,
2529 kPointerSize, SMI_PARAMETERS);
2534 Label not_function_prototype(
this, Label::kDeferred);
2535 GotoIfNot(InstanceTypeEqual(instance_type, JS_FUNCTION_TYPE),
2536 ¬_function_prototype);
2537 GotoIfNot(IsPrototypeString(p->name), ¬_function_prototype);
2539 GotoIfPrototypeRequiresRuntimeLookup(CAST(receiver), CAST(receiver_map),
2540 ¬_function_prototype);
2541 Return(LoadJSFunctionPrototype(receiver, &miss));
2542 BIND(¬_function_prototype);
2545 GenericPropertyLoad(receiver, receiver_map, instance_type, p, &miss,
2551 StoreFeedbackVectorSlot(p->vector, p->slot,
2552 LoadRoot(RootIndex::kuninitialized_symbol),
2553 SKIP_WRITE_BARRIER, 0, SMI_PARAMETERS);
2555 TailCallRuntime(Runtime::kLoadIC_Miss, p->context, p->receiver, p->name,
2556 p->slot, p->vector);
2560 void AccessorAssembler::LoadGlobalIC(TNode<FeedbackVector> vector, Node* slot,
2561 const LazyNode<Context>& lazy_context,
2562 const LazyNode<Name>& lazy_name,
2563 TypeofMode typeof_mode,
2564 ExitPoint* exit_point,
2565 ParameterMode slot_mode) {
2566 Label try_handler(
this, Label::kDeferred), miss(
this, Label::kDeferred);
2567 LoadGlobalIC_TryPropertyCellCase(vector, slot, lazy_context, exit_point,
2568 &try_handler, &miss, slot_mode);
2571 LoadGlobalIC_TryHandlerCase(vector, slot, lazy_context, lazy_name,
2572 typeof_mode, exit_point, &miss, slot_mode);
2576 Comment(
"LoadGlobalIC_MissCase");
2577 TNode<Context> context = lazy_context();
2578 TNode<Name> name = lazy_name();
2579 exit_point->ReturnCallRuntime(Runtime::kLoadGlobalIC_Miss, context, name,
2580 ParameterToTagged(slot, slot_mode), vector);
2584 void AccessorAssembler::LoadGlobalIC_TryPropertyCellCase(
2585 TNode<FeedbackVector> vector, Node* slot,
2586 const LazyNode<Context>& lazy_context, ExitPoint* exit_point,
2587 Label* try_handler, Label* miss, ParameterMode slot_mode) {
2588 Comment(
"LoadGlobalIC_TryPropertyCellCase");
2590 Label if_lexical_var(
this), if_property_cell(
this);
2591 TNode<MaybeObject> maybe_weak_ref =
2592 LoadFeedbackVectorSlot(vector, slot, 0, slot_mode);
2593 Branch(TaggedIsSmi(maybe_weak_ref), &if_lexical_var, &if_property_cell);
2595 BIND(&if_property_cell);
2598 CSA_ASSERT(
this, IsWeakOrCleared(maybe_weak_ref));
2599 TNode<PropertyCell> property_cell =
2600 CAST(GetHeapObjectAssumeWeak(maybe_weak_ref, try_handler));
2601 TNode<Object> value =
2602 LoadObjectField(property_cell, PropertyCell::kValueOffset);
2603 GotoIf(WordEqual(value, TheHoleConstant()), miss);
2604 exit_point->Return(value);
2607 BIND(&if_lexical_var);
2609 Comment(
"Load lexical variable");
2610 TNode<IntPtrT> lexical_handler = SmiUntag(CAST(maybe_weak_ref));
2611 TNode<IntPtrT> context_index =
2612 Signed(DecodeWord<FeedbackNexus::ContextIndexBits>(lexical_handler));
2613 TNode<IntPtrT> slot_index =
2614 Signed(DecodeWord<FeedbackNexus::SlotIndexBits>(lexical_handler));
2615 TNode<Context> context = lazy_context();
2616 TNode<Context> script_context = LoadScriptContext(context, context_index);
2617 TNode<Object> result = LoadContextElement(script_context, slot_index);
2618 exit_point->Return(result);
2622 void AccessorAssembler::LoadGlobalIC_TryHandlerCase(
2623 TNode<FeedbackVector> vector, Node* slot,
2624 const LazyNode<Context>& lazy_context,
const LazyNode<Name>& lazy_name,
2625 TypeofMode typeof_mode, ExitPoint* exit_point, Label* miss,
2626 ParameterMode slot_mode) {
2627 Comment(
"LoadGlobalIC_TryHandlerCase");
2629 Label call_handler(
this), non_smi(
this);
2631 TNode<MaybeObject> feedback_element =
2632 LoadFeedbackVectorSlot(vector, slot, kPointerSize, slot_mode);
2633 TNode<Object> handler = CAST(feedback_element);
2634 GotoIf(WordEqual(handler, LoadRoot(RootIndex::kuninitialized_symbol)), miss);
2636 OnNonExistent on_nonexistent = typeof_mode == NOT_INSIDE_TYPEOF
2637 ? OnNonExistent::kThrowReferenceError
2638 : OnNonExistent::kReturnUndefined;
2640 TNode<Context> context = lazy_context();
2641 TNode<Context> native_context = LoadNativeContext(context);
2642 TNode<JSGlobalProxy> receiver =
2643 CAST(LoadContextElement(native_context, Context::GLOBAL_PROXY_INDEX));
2644 Node* holder = LoadContextElement(native_context, Context::EXTENSION_INDEX);
2646 LoadICParameters p(context, receiver, lazy_name(),
2647 ParameterToTagged(slot, slot_mode), vector, holder);
2649 HandleLoadICHandlerCase(&p, handler, miss, exit_point, ICMode::kGlobalIC,
2653 void AccessorAssembler::KeyedLoadIC(
const LoadICParameters* p) {
2654 ExitPoint direct_exit(
this);
2656 TVARIABLE(MaybeObject, var_handler);
2657 Label if_handler(
this, &var_handler), try_polymorphic(
this, Label::kDeferred),
2658 try_megamorphic(
this, Label::kDeferred),
2659 try_polymorphic_name(
this, Label::kDeferred),
2660 miss(
this, Label::kDeferred);
2662 Node* receiver_map = LoadReceiverMap(p->receiver);
2663 GotoIf(IsDeprecatedMap(receiver_map), &miss);
2666 TNode<MaybeObject> feedback =
2667 TryMonomorphicCase(p->slot, p->vector, receiver_map, &if_handler,
2668 &var_handler, &try_polymorphic);
2671 HandleLoadICHandlerCase(p, CAST(var_handler.value()), &miss, &direct_exit,
2672 ICMode::kNonGlobalIC,
2673 OnNonExistent::kReturnUndefined, kSupportElements);
2676 BIND(&try_polymorphic);
2677 TNode<HeapObject> strong_feedback = GetHeapObjectIfStrong(feedback, &miss);
2680 Comment(
"KeyedLoadIC_try_polymorphic");
2681 GotoIfNot(IsWeakFixedArrayMap(LoadMap(strong_feedback)), &try_megamorphic);
2682 HandlePolymorphicCase(receiver_map, CAST(strong_feedback), &if_handler,
2683 &var_handler, &miss, 2);
2686 BIND(&try_megamorphic);
2689 Comment(
"KeyedLoadIC_try_megamorphic");
2691 WordEqual(strong_feedback, LoadRoot(RootIndex::kmegamorphic_symbol)),
2692 &try_polymorphic_name);
2694 TailCallBuiltin(Builtins::kKeyedLoadIC_Megamorphic, p->context, p->receiver,
2695 p->name, p->slot, p->vector);
2697 BIND(&try_polymorphic_name);
2701 Node* name = p->name;
2702 Comment(
"KeyedLoadIC_try_polymorphic_name");
2703 VARIABLE(var_name, MachineRepresentation::kTagged, name);
2704 VARIABLE(var_index, MachineType::PointerRepresentation());
2705 Label if_polymorphic_name(
this, &var_name), if_internalized(
this),
2706 if_notinternalized(
this, Label::kDeferred);
2709 GotoIf(WordEqual(strong_feedback, name), &if_polymorphic_name);
2712 TryToName(name, &miss, &var_index, &if_internalized, &var_name, &miss,
2713 &if_notinternalized);
2715 BIND(&if_internalized);
2718 Branch(WordEqual(strong_feedback, var_name.value()), &if_polymorphic_name,
2722 BIND(&if_notinternalized);
2725 Node*
function = ExternalConstant(
2726 ExternalReference::try_internalize_string_function());
2727 Node*
const isolate_ptr =
2728 ExternalConstant(ExternalReference::isolate_address(isolate()));
2729 var_name.Bind(CallCFunction2(
2730 MachineType::AnyTagged(), MachineType::Pointer(),
2731 MachineType::AnyTagged(),
function, isolate_ptr, name));
2732 Goto(&if_internalized);
2735 BIND(&if_polymorphic_name);
2739 Node* name = var_name.value();
2740 TailCallBuiltin(Builtins::kKeyedLoadIC_PolymorphicName, p->context,
2741 p->receiver, name, p->slot, p->vector);
2747 Comment(
"KeyedLoadIC_miss");
2748 TailCallRuntime(Runtime::kKeyedLoadIC_Miss, p->context, p->receiver,
2749 p->name, p->slot, p->vector);
2753 void AccessorAssembler::KeyedLoadICGeneric(
const LoadICParameters* p) {
2754 VARIABLE(var_index, MachineType::PointerRepresentation());
2755 VARIABLE(var_unique, MachineRepresentation::kTagged, p->name);
2756 Label if_index(
this), if_unique_name(
this), if_notunique(
this),
2757 if_other(
this, Label::kDeferred), if_runtime(
this, Label::kDeferred);
2759 Node* receiver = p->receiver;
2760 GotoIf(TaggedIsSmi(receiver), &if_runtime);
2762 TryToName(p->name, &if_index, &var_index, &if_unique_name, &var_unique,
2763 &if_other, &if_notunique);
2767 Node* name = CallBuiltin(Builtins::kToName, p->context, p->name);
2768 var_unique.Bind(name);
2769 TryToName(name, &if_index, &var_index, &if_unique_name, &var_unique,
2770 &if_runtime, &if_notunique);
2775 Node* receiver_map = LoadMap(receiver);
2776 Node* instance_type = LoadMapInstanceType(receiver_map);
2777 GenericElementLoad(receiver, receiver_map, instance_type, var_index.value(),
2781 BIND(&if_unique_name);
2783 LoadICParameters pp = *p;
2784 pp.name = var_unique.value();
2785 Node* receiver_map = LoadMap(receiver);
2786 Node* instance_type = LoadMapInstanceType(receiver_map);
2787 GenericPropertyLoad(receiver, receiver_map, instance_type, &pp,
2791 BIND(&if_notunique);
2793 if (FLAG_internalize_on_the_fly) {
2798 Label if_in_string_table(
this);
2799 TryInternalizeString(var_unique.value(), &if_index, &var_index,
2800 &if_in_string_table, &var_unique, &if_runtime,
2803 BIND(&if_in_string_table);
2810 LoadICParameters pp = *p;
2811 pp.name = var_unique.value();
2812 Node* receiver_map = LoadMap(receiver);
2813 Node* instance_type = LoadMapInstanceType(receiver_map);
2814 GenericPropertyLoad(receiver, receiver_map, instance_type, &pp,
2815 &if_runtime, kDontUseStubCache);
2824 Comment(
"KeyedLoadGeneric_slow");
2825 IncrementCounter(isolate()->counters()->ic_keyed_load_generic_slow(), 1);
2827 TailCallRuntime(Runtime::kGetProperty, p->context, p->receiver,
2828 var_unique.value());
2832 void AccessorAssembler::KeyedLoadICPolymorphicName(
const LoadICParameters* p) {
2833 TVARIABLE(MaybeObject, var_handler);
2834 Label if_handler(
this, &var_handler), miss(
this, Label::kDeferred);
2836 Node* receiver = p->receiver;
2837 Node* receiver_map = LoadReceiverMap(receiver);
2838 Node* name = p->name;
2839 Node* vector = p->vector;
2840 Node* slot = p->slot;
2841 Node* context = p->context;
2846 CSA_ASSERT(
this, IsName(name));
2847 CSA_ASSERT(
this, Word32BinaryNot(IsDeprecatedMap(receiver_map)));
2848 CSA_ASSERT(
this, WordEqual(name, CAST(LoadFeedbackVectorSlot(
2849 vector, slot, 0, SMI_PARAMETERS))));
2852 TNode<MaybeObject> feedback_element =
2853 LoadFeedbackVectorSlot(vector, slot, kPointerSize, SMI_PARAMETERS);
2854 TNode<WeakFixedArray> array = CAST(feedback_element);
2855 HandlePolymorphicCase(receiver_map, array, &if_handler, &var_handler, &miss,
2860 ExitPoint direct_exit(
this);
2861 HandleLoadICHandlerCase(p, CAST(var_handler.value()), &miss, &direct_exit,
2862 ICMode::kNonGlobalIC,
2863 OnNonExistent::kReturnUndefined, kOnlyProperties);
2868 Comment(
"KeyedLoadIC_miss");
2869 TailCallRuntime(Runtime::kKeyedLoadIC_Miss, context, receiver, name, slot,
2874 void AccessorAssembler::StoreIC(
const StoreICParameters* p) {
2875 TVARIABLE(MaybeObject, var_handler,
2876 ReinterpretCast<MaybeObject>(SmiConstant(0)));
2878 Label if_handler(
this, &var_handler),
2879 if_handler_from_stub_cache(
this, &var_handler, Label::kDeferred),
2880 try_polymorphic(
this, Label::kDeferred),
2881 try_megamorphic(
this, Label::kDeferred),
2882 try_uninitialized(
this, Label::kDeferred), miss(
this, Label::kDeferred);
2884 Node* receiver_map = LoadReceiverMap(p->receiver);
2885 GotoIf(IsDeprecatedMap(receiver_map), &miss);
2888 TNode<MaybeObject> feedback =
2889 TryMonomorphicCase(p->slot, p->vector, receiver_map, &if_handler,
2890 &var_handler, &try_polymorphic);
2893 Comment(
"StoreIC_if_handler");
2894 HandleStoreICHandlerCase(p, var_handler.value(), &miss,
2895 ICMode::kNonGlobalIC);
2898 BIND(&try_polymorphic);
2899 TNode<HeapObject> strong_feedback = GetHeapObjectIfStrong(feedback, &miss);
2902 Comment(
"StoreIC_try_polymorphic");
2903 GotoIfNot(IsWeakFixedArrayMap(LoadMap(strong_feedback)), &try_megamorphic);
2904 HandlePolymorphicCase(receiver_map, CAST(strong_feedback), &if_handler,
2905 &var_handler, &miss, 2);
2908 BIND(&try_megamorphic);
2912 WordEqual(strong_feedback, LoadRoot(RootIndex::kmegamorphic_symbol)),
2913 &try_uninitialized);
2915 TryProbeStubCache(isolate()->store_stub_cache(), p->receiver, p->name,
2916 &if_handler, &var_handler, &miss);
2918 BIND(&try_uninitialized);
2922 WordEqual(strong_feedback, LoadRoot(RootIndex::kuninitialized_symbol)),
2924 TailCallBuiltin(Builtins::kStoreIC_Uninitialized, p->context, p->receiver,
2925 p->name, p->value, p->slot, p->vector);
2929 TailCallRuntime(Runtime::kStoreIC_Miss, p->context, p->value, p->slot,
2930 p->vector, p->receiver, p->name);
2934 void AccessorAssembler::StoreGlobalIC(
const StoreICParameters* pp) {
2935 Label if_lexical_var(
this), if_property_cell(
this);
2936 TNode<MaybeObject> maybe_weak_ref =
2937 LoadFeedbackVectorSlot(pp->vector, pp->slot, 0, SMI_PARAMETERS);
2938 Branch(TaggedIsSmi(maybe_weak_ref), &if_lexical_var, &if_property_cell);
2940 BIND(&if_property_cell);
2942 Label try_handler(
this), miss(
this, Label::kDeferred);
2943 CSA_ASSERT(
this, IsWeakOrCleared(maybe_weak_ref));
2944 TNode<PropertyCell> property_cell =
2945 CAST(GetHeapObjectAssumeWeak(maybe_weak_ref, &try_handler));
2947 ExitPoint direct_exit(
this);
2948 StoreGlobalIC_PropertyCellCase(property_cell, pp->value, &direct_exit,
2953 Comment(
"StoreGlobalIC_try_handler");
2954 TNode<MaybeObject> handler = LoadFeedbackVectorSlot(
2955 pp->vector, pp->slot, kPointerSize, SMI_PARAMETERS);
2957 GotoIf(WordEqual(handler, LoadRoot(RootIndex::kuninitialized_symbol)),
2960 StoreICParameters p = *pp;
2961 DCHECK_NULL(p.receiver);
2962 Node* native_context = LoadNativeContext(p.context);
2964 LoadContextElement(native_context, Context::GLOBAL_PROXY_INDEX);
2966 HandleStoreICHandlerCase(&p, handler, &miss, ICMode::kGlobalIC);
2971 TailCallRuntime(Runtime::kStoreGlobalIC_Miss, pp->context, pp->value,
2972 pp->slot, pp->vector, pp->name);
2976 BIND(&if_lexical_var);
2978 Comment(
"Store lexical variable");
2979 TNode<IntPtrT> lexical_handler = SmiUntag(CAST(maybe_weak_ref));
2980 TNode<IntPtrT> context_index =
2981 Signed(DecodeWord<FeedbackNexus::ContextIndexBits>(lexical_handler));
2982 TNode<IntPtrT> slot_index =
2983 Signed(DecodeWord<FeedbackNexus::SlotIndexBits>(lexical_handler));
2984 TNode<Context> script_context =
2985 LoadScriptContext(CAST(pp->context), context_index);
2986 StoreContextElement(script_context, slot_index, pp->value);
2991 void AccessorAssembler::StoreGlobalIC_PropertyCellCase(Node* property_cell,
2993 ExitPoint* exit_point,
2995 Comment(
"StoreGlobalIC_TryPropertyCellCase");
2996 CSA_ASSERT(
this, IsPropertyCell(property_cell));
3001 Node* cell_contents =
3002 LoadObjectField(property_cell, PropertyCell::kValueOffset);
3003 Node* details = LoadAndUntagToWord32ObjectField(property_cell,
3004 PropertyCell::kDetailsOffset);
3005 GotoIf(IsSetWord32(details, PropertyDetails::kAttributesReadOnlyMask), miss);
3007 Word32Equal(DecodeWord32<PropertyDetails::KindField>(details),
3008 Int32Constant(kData)));
3010 Node* type = DecodeWord32<PropertyDetails::PropertyCellTypeField>(details);
3012 Label constant(
this), store(
this), not_smi(
this);
3014 GotoIf(Word32Equal(type, Int32Constant(
3015 static_cast<int>(PropertyCellType::kConstant))),
3018 GotoIf(IsTheHole(cell_contents), miss);
3021 type, Int32Constant(static_cast<int>(PropertyCellType::kMutable))),
3024 Word32Or(Word32Equal(type, Int32Constant(static_cast<int>(
3025 PropertyCellType::kConstantType))),
3026 Word32Equal(type, Int32Constant(static_cast<int>(
3027 PropertyCellType::kUndefined)))));
3029 GotoIfNot(TaggedIsSmi(cell_contents), ¬_smi);
3030 GotoIfNot(TaggedIsSmi(value), miss);
3035 GotoIf(TaggedIsSmi(value), miss);
3036 Node* expected_map = LoadMap(cell_contents);
3037 Node* map = LoadMap(value);
3038 GotoIfNot(WordEqual(expected_map, map), miss);
3044 StoreObjectField(property_cell, PropertyCell::kValueOffset, value);
3045 exit_point->Return(value);
3050 GotoIfNot(WordEqual(cell_contents, value), miss);
3051 exit_point->Return(value);
3055 void AccessorAssembler::KeyedStoreIC(
const StoreICParameters* p) {
3056 Label miss(
this, Label::kDeferred);
3058 TVARIABLE(MaybeObject, var_handler);
3060 Label if_handler(
this, &var_handler),
3061 try_polymorphic(
this, Label::kDeferred),
3062 try_megamorphic(
this, Label::kDeferred),
3063 try_polymorphic_name(
this, Label::kDeferred);
3065 Node* receiver_map = LoadReceiverMap(p->receiver);
3066 GotoIf(IsDeprecatedMap(receiver_map), &miss);
3069 TNode<MaybeObject> feedback =
3070 TryMonomorphicCase(p->slot, p->vector, receiver_map, &if_handler,
3071 &var_handler, &try_polymorphic);
3074 Comment(
"KeyedStoreIC_if_handler");
3075 HandleStoreICHandlerCase(p, var_handler.value(), &miss,
3076 ICMode::kNonGlobalIC, kSupportElements);
3079 BIND(&try_polymorphic);
3080 TNode<HeapObject> strong_feedback = GetHeapObjectIfStrong(feedback, &miss);
3083 Comment(
"KeyedStoreIC_try_polymorphic");
3084 GotoIfNot(IsWeakFixedArrayMap(LoadMap(strong_feedback)),
3086 HandlePolymorphicCase(receiver_map, CAST(strong_feedback), &if_handler,
3087 &var_handler, &miss, 2);
3090 BIND(&try_megamorphic);
3093 Comment(
"KeyedStoreIC_try_megamorphic");
3095 WordEqual(strong_feedback, LoadRoot(RootIndex::kmegamorphic_symbol)),
3096 &try_polymorphic_name);
3097 TailCallBuiltin(Builtins::kKeyedStoreIC_Megamorphic, p->context,
3098 p->receiver, p->name, p->value, p->slot, p->vector);
3101 BIND(&try_polymorphic_name);
3104 Comment(
"KeyedStoreIC_try_polymorphic_name");
3105 GotoIfNot(WordEqual(strong_feedback, p->name), &miss);
3108 TNode<MaybeObject> feedback_element = LoadFeedbackVectorSlot(
3109 p->vector, p->slot, kPointerSize, SMI_PARAMETERS);
3110 TNode<WeakFixedArray> array = CAST(feedback_element);
3111 HandlePolymorphicCase(receiver_map, array, &if_handler, &var_handler,
3117 Comment(
"KeyedStoreIC_miss");
3118 TailCallRuntime(Runtime::kKeyedStoreIC_Miss, p->context, p->value, p->slot,
3119 p->vector, p->receiver, p->name);
3123 void AccessorAssembler::StoreInArrayLiteralIC(
const StoreICParameters* p) {
3124 Label miss(
this, Label::kDeferred);
3126 TVARIABLE(MaybeObject, var_handler);
3128 Label if_handler(
this, &var_handler),
3129 try_polymorphic(
this, Label::kDeferred),
3130 try_megamorphic(
this, Label::kDeferred);
3132 Node* array_map = LoadReceiverMap(p->receiver);
3133 GotoIf(IsDeprecatedMap(array_map), &miss);
3134 TNode<MaybeObject> feedback =
3135 TryMonomorphicCase(p->slot, p->vector, array_map, &if_handler,
3136 &var_handler, &try_polymorphic);
3140 Comment(
"StoreInArrayLiteralIC_if_handler");
3143 TNode<HeapObject> handler = CAST(var_handler.value());
3144 Label if_transitioning_element_store(
this);
3145 GotoIfNot(IsCode(handler), &if_transitioning_element_store);
3146 TailCallStub(StoreWithVectorDescriptor{}, CAST(handler), CAST(p->context),
3147 p->receiver, p->name, p->value, p->slot, p->vector);
3149 BIND(&if_transitioning_element_store);
3151 TNode<MaybeObject> maybe_transition_map =
3152 LoadHandlerDataField(CAST(handler), 1);
3153 TNode<Map> transition_map =
3154 CAST(GetHeapObjectAssumeWeak(maybe_transition_map, &miss));
3155 GotoIf(IsDeprecatedMap(transition_map), &miss);
3156 Node* code = LoadObjectField(handler, StoreHandler::kSmiHandlerOffset);
3157 CSA_ASSERT(
this, IsCode(code));
3158 TailCallStub(StoreTransitionDescriptor{}, code, p->context, p->receiver,
3159 p->name, transition_map, p->value, p->slot, p->vector);
3163 BIND(&try_polymorphic);
3164 TNode<HeapObject> strong_feedback = GetHeapObjectIfStrong(feedback, &miss);
3166 Comment(
"StoreInArrayLiteralIC_try_polymorphic");
3167 GotoIfNot(IsWeakFixedArrayMap(LoadMap(strong_feedback)),
3169 HandlePolymorphicCase(array_map, CAST(strong_feedback), &if_handler,
3170 &var_handler, &miss, 2);
3173 BIND(&try_megamorphic);
3175 Comment(
"StoreInArrayLiteralIC_try_megamorphic");
3177 Word32Or(WordEqual(strong_feedback,
3178 LoadRoot(RootIndex::kuninitialized_symbol)),
3179 WordEqual(strong_feedback,
3180 LoadRoot(RootIndex::kmegamorphic_symbol))));
3182 WordEqual(strong_feedback, LoadRoot(RootIndex::kmegamorphic_symbol)),
3184 TailCallRuntime(Runtime::kStoreInArrayLiteralIC_Slow, p->context,
3185 p->value, p->receiver, p->name);
3191 Comment(
"StoreInArrayLiteralIC_miss");
3193 TailCallRuntime(Runtime::kKeyedStoreIC_Miss, p->context, p->value, p->slot,
3194 p->vector, p->receiver, p->name);
3200 void AccessorAssembler::GenerateLoadIC() {
3201 typedef LoadWithVectorDescriptor Descriptor;
3203 Node* receiver = Parameter(Descriptor::kReceiver);
3204 Node* name = Parameter(Descriptor::kName);
3205 Node* slot = Parameter(Descriptor::kSlot);
3206 Node* vector = Parameter(Descriptor::kVector);
3207 Node* context = Parameter(Descriptor::kContext);
3209 LoadICParameters p(context, receiver, name, slot, vector);
3213 void AccessorAssembler::GenerateLoadIC_Megamorphic() {
3214 typedef LoadWithVectorDescriptor Descriptor;
3216 Node* receiver = Parameter(Descriptor::kReceiver);
3217 Node* name = Parameter(Descriptor::kName);
3218 Node* slot = Parameter(Descriptor::kSlot);
3219 Node* vector = Parameter(Descriptor::kVector);
3220 Node* context = Parameter(Descriptor::kContext);
3222 ExitPoint direct_exit(
this);
3223 TVARIABLE(MaybeObject, var_handler);
3224 Label if_handler(
this, &var_handler), miss(
this, Label::kDeferred);
3226 TryProbeStubCache(isolate()->load_stub_cache(), receiver, name, &if_handler,
3227 &var_handler, &miss);
3230 LoadICParameters p(context, receiver, name, slot, vector);
3231 HandleLoadICHandlerCase(&p, CAST(var_handler.value()), &miss, &direct_exit);
3234 direct_exit.ReturnCallRuntime(Runtime::kLoadIC_Miss, context, receiver, name,
3238 void AccessorAssembler::GenerateLoadIC_Noninlined() {
3239 typedef LoadWithVectorDescriptor Descriptor;
3241 Node* receiver = Parameter(Descriptor::kReceiver);
3242 Node* name = Parameter(Descriptor::kName);
3243 Node* slot = Parameter(Descriptor::kSlot);
3244 Node* vector = Parameter(Descriptor::kVector);
3245 Node* context = Parameter(Descriptor::kContext);
3247 ExitPoint direct_exit(
this);
3248 TVARIABLE(MaybeObject, var_handler);
3249 Label if_handler(
this, &var_handler), miss(
this, Label::kDeferred);
3251 Node* receiver_map = LoadReceiverMap(receiver);
3252 TNode<MaybeObject> feedback_element =
3253 LoadFeedbackVectorSlot(vector, slot, 0, SMI_PARAMETERS);
3254 TNode<HeapObject> feedback = CAST(feedback_element);
3256 LoadICParameters p(context, receiver, name, slot, vector);
3257 LoadIC_Noninlined(&p, receiver_map, feedback, &var_handler, &if_handler,
3258 &miss, &direct_exit);
3261 HandleLoadICHandlerCase(&p, CAST(var_handler.value()), &miss, &direct_exit);
3264 direct_exit.ReturnCallRuntime(Runtime::kLoadIC_Miss, context, receiver, name,
3268 void AccessorAssembler::GenerateLoadIC_Uninitialized() {
3269 typedef LoadWithVectorDescriptor Descriptor;
3271 Node* receiver = Parameter(Descriptor::kReceiver);
3272 Node* name = Parameter(Descriptor::kName);
3273 Node* slot = Parameter(Descriptor::kSlot);
3274 Node* vector = Parameter(Descriptor::kVector);
3275 Node* context = Parameter(Descriptor::kContext);
3277 LoadICParameters p(context, receiver, name, slot, vector);
3278 LoadIC_Uninitialized(&p);
3281 void AccessorAssembler::GenerateLoadICTrampoline() {
3282 typedef LoadDescriptor Descriptor;
3284 Node* receiver = Parameter(Descriptor::kReceiver);
3285 Node* name = Parameter(Descriptor::kName);
3286 Node* slot = Parameter(Descriptor::kSlot);
3287 Node* context = Parameter(Descriptor::kContext);
3288 Node* vector = LoadFeedbackVectorForStub();
3290 TailCallBuiltin(Builtins::kLoadIC, context, receiver, name, slot, vector);
3293 void AccessorAssembler::GenerateLoadICTrampoline_Megamorphic() {
3294 typedef LoadDescriptor Descriptor;
3296 Node* receiver = Parameter(Descriptor::kReceiver);
3297 Node* name = Parameter(Descriptor::kName);
3298 Node* slot = Parameter(Descriptor::kSlot);
3299 Node* context = Parameter(Descriptor::kContext);
3300 Node* vector = LoadFeedbackVectorForStub();
3302 TailCallBuiltin(Builtins::kLoadIC_Megamorphic, context, receiver, name, slot,
3306 void AccessorAssembler::GenerateLoadGlobalIC(TypeofMode typeof_mode) {
3307 typedef LoadGlobalWithVectorDescriptor Descriptor;
3309 Node* name = Parameter(Descriptor::kName);
3310 Node* slot = Parameter(Descriptor::kSlot);
3311 Node* vector = Parameter(Descriptor::kVector);
3312 Node* context = Parameter(Descriptor::kContext);
3314 ExitPoint direct_exit(
this);
3315 LoadGlobalIC(CAST(vector), slot,
3317 [=] {
return CAST(context); },
3319 [=] {
return CAST(name); }, typeof_mode, &direct_exit);
3322 void AccessorAssembler::GenerateLoadGlobalICTrampoline(TypeofMode typeof_mode) {
3323 typedef LoadGlobalDescriptor Descriptor;
3325 Node* name = Parameter(Descriptor::kName);
3326 Node* slot = Parameter(Descriptor::kSlot);
3327 Node* context = Parameter(Descriptor::kContext);
3328 Node* vector = LoadFeedbackVectorForStub();
3331 CodeFactory::LoadGlobalICInOptimizedCode(isolate(), typeof_mode);
3332 TailCallStub(callable, context, name, slot, vector);
3335 void AccessorAssembler::GenerateKeyedLoadIC() {
3336 typedef LoadWithVectorDescriptor Descriptor;
3338 Node* receiver = Parameter(Descriptor::kReceiver);
3339 Node* name = Parameter(Descriptor::kName);
3340 Node* slot = Parameter(Descriptor::kSlot);
3341 Node* vector = Parameter(Descriptor::kVector);
3342 Node* context = Parameter(Descriptor::kContext);
3344 LoadICParameters p(context, receiver, name, slot, vector);
3348 void AccessorAssembler::GenerateKeyedLoadIC_Megamorphic() {
3349 typedef LoadWithVectorDescriptor Descriptor;
3351 Node* receiver = Parameter(Descriptor::kReceiver);
3352 Node* name = Parameter(Descriptor::kName);
3353 Node* slot = Parameter(Descriptor::kSlot);
3354 Node* vector = Parameter(Descriptor::kVector);
3355 Node* context = Parameter(Descriptor::kContext);
3357 LoadICParameters p(context, receiver, name, slot, vector);
3358 KeyedLoadICGeneric(&p);
3361 void AccessorAssembler::GenerateKeyedLoadICTrampoline() {
3362 typedef LoadDescriptor Descriptor;
3364 Node* receiver = Parameter(Descriptor::kReceiver);
3365 Node* name = Parameter(Descriptor::kName);
3366 Node* slot = Parameter(Descriptor::kSlot);
3367 Node* context = Parameter(Descriptor::kContext);
3368 Node* vector = LoadFeedbackVectorForStub();
3370 TailCallBuiltin(Builtins::kKeyedLoadIC, context, receiver, name, slot,
3374 void AccessorAssembler::GenerateKeyedLoadICTrampoline_Megamorphic() {
3375 typedef LoadDescriptor Descriptor;
3377 Node* receiver = Parameter(Descriptor::kReceiver);
3378 Node* name = Parameter(Descriptor::kName);
3379 Node* slot = Parameter(Descriptor::kSlot);
3380 Node* context = Parameter(Descriptor::kContext);
3381 Node* vector = LoadFeedbackVectorForStub();
3383 TailCallBuiltin(Builtins::kKeyedLoadIC_Megamorphic, context, receiver, name,
3387 void AccessorAssembler::GenerateKeyedLoadIC_PolymorphicName() {
3388 typedef LoadWithVectorDescriptor Descriptor;
3390 Node* receiver = Parameter(Descriptor::kReceiver);
3391 Node* name = Parameter(Descriptor::kName);
3392 Node* slot = Parameter(Descriptor::kSlot);
3393 Node* vector = Parameter(Descriptor::kVector);
3394 Node* context = Parameter(Descriptor::kContext);
3396 LoadICParameters p(context, receiver, name, slot, vector);
3397 KeyedLoadICPolymorphicName(&p);
3400 void AccessorAssembler::GenerateStoreGlobalIC() {
3401 typedef StoreGlobalWithVectorDescriptor Descriptor;
3403 Node* name = Parameter(Descriptor::kName);
3404 Node* value = Parameter(Descriptor::kValue);
3405 Node* slot = Parameter(Descriptor::kSlot);
3406 Node* vector = Parameter(Descriptor::kVector);
3407 Node* context = Parameter(Descriptor::kContext);
3409 StoreICParameters p(context,
nullptr, name, value, slot, vector);
3413 void AccessorAssembler::GenerateStoreGlobalICTrampoline() {
3414 typedef StoreGlobalDescriptor Descriptor;
3416 Node* name = Parameter(Descriptor::kName);
3417 Node* value = Parameter(Descriptor::kValue);
3418 Node* slot = Parameter(Descriptor::kSlot);
3419 Node* context = Parameter(Descriptor::kContext);
3420 Node* vector = LoadFeedbackVectorForStub();
3422 TailCallBuiltin(Builtins::kStoreGlobalIC, context, name, value, slot, vector);
3425 void AccessorAssembler::GenerateStoreIC() {
3426 typedef StoreWithVectorDescriptor Descriptor;
3428 Node* receiver = Parameter(Descriptor::kReceiver);
3429 Node* name = Parameter(Descriptor::kName);
3430 Node* value = Parameter(Descriptor::kValue);
3431 Node* slot = Parameter(Descriptor::kSlot);
3432 Node* vector = Parameter(Descriptor::kVector);
3433 Node* context = Parameter(Descriptor::kContext);
3435 StoreICParameters p(context, receiver, name, value, slot, vector);
3439 void AccessorAssembler::GenerateStoreICTrampoline() {
3440 typedef StoreDescriptor Descriptor;
3442 Node* receiver = Parameter(Descriptor::kReceiver);
3443 Node* name = Parameter(Descriptor::kName);
3444 Node* value = Parameter(Descriptor::kValue);
3445 Node* slot = Parameter(Descriptor::kSlot);
3446 Node* context = Parameter(Descriptor::kContext);
3447 Node* vector = LoadFeedbackVectorForStub();
3449 TailCallBuiltin(Builtins::kStoreIC, context, receiver, name, value, slot,
3453 void AccessorAssembler::GenerateKeyedStoreIC() {
3454 typedef StoreWithVectorDescriptor Descriptor;
3456 Node* receiver = Parameter(Descriptor::kReceiver);
3457 Node* name = Parameter(Descriptor::kName);
3458 Node* value = Parameter(Descriptor::kValue);
3459 Node* slot = Parameter(Descriptor::kSlot);
3460 Node* vector = Parameter(Descriptor::kVector);
3461 Node* context = Parameter(Descriptor::kContext);
3463 StoreICParameters p(context, receiver, name, value, slot, vector);
3467 void AccessorAssembler::GenerateKeyedStoreICTrampoline() {
3468 typedef StoreDescriptor Descriptor;
3470 Node* receiver = Parameter(Descriptor::kReceiver);
3471 Node* name = Parameter(Descriptor::kName);
3472 Node* value = Parameter(Descriptor::kValue);
3473 Node* slot = Parameter(Descriptor::kSlot);
3474 Node* context = Parameter(Descriptor::kContext);
3475 Node* vector = LoadFeedbackVectorForStub();
3477 TailCallBuiltin(Builtins::kKeyedStoreIC, context, receiver, name, value, slot,
3481 void AccessorAssembler::GenerateStoreInArrayLiteralIC() {
3482 typedef StoreWithVectorDescriptor Descriptor;
3484 Node* array = Parameter(Descriptor::kReceiver);
3485 Node* index = Parameter(Descriptor::kName);
3486 Node* value = Parameter(Descriptor::kValue);
3487 Node* slot = Parameter(Descriptor::kSlot);
3488 Node* vector = Parameter(Descriptor::kVector);
3489 Node* context = Parameter(Descriptor::kContext);
3491 StoreICParameters p(context, array, index, value, slot, vector);
3492 StoreInArrayLiteralIC(&p);
3495 void AccessorAssembler::GenerateCloneObjectIC_Slow() {
3496 typedef CloneObjectWithVectorDescriptor Descriptor;
3497 TNode<HeapObject> source = CAST(Parameter(Descriptor::kSource));
3498 TNode<Smi> flags = CAST(Parameter(Descriptor::kFlags));
3499 TNode<Context> context = CAST(Parameter(Descriptor::kContext));
3505 TNode<Context> native_context = LoadNativeContext(context);
3506 TNode<JSFunction> object_fn =
3507 CAST(LoadContextElement(native_context, Context::OBJECT_FUNCTION_INDEX));
3508 TNode<Map> initial_map = CAST(
3509 LoadObjectField(object_fn, JSFunction::kPrototypeOrInitialMapOffset));
3510 CSA_ASSERT(
this, IsMap(initial_map));
3512 TNode<JSObject> result = CAST(AllocateJSObjectFromMap(initial_map));
3515 Label did_set_proto_if_needed(
this);
3516 TNode<BoolT> is_null_proto = SmiNotEqual(
3517 SmiAnd(flags, SmiConstant(ObjectLiteral::kHasNullPrototype)),
3518 SmiConstant(Smi::zero()));
3519 GotoIfNot(is_null_proto, &did_set_proto_if_needed);
3521 CallRuntime(Runtime::kInternalSetPrototype, context, result,
3524 Goto(&did_set_proto_if_needed);
3525 BIND(&did_set_proto_if_needed);
3528 ReturnIf(IsNullOrUndefined(source), result);
3530 CSA_ASSERT(
this, IsJSReceiver(source));
3532 Label call_runtime(
this, Label::kDeferred);
3535 TNode<Map> map = LoadMap(source);
3536 TNode<Int32T> type = LoadMapInstanceType(map);
3539 GotoIf(IsJSObjectInstanceType(type), &cont);
3540 GotoIfNot(IsStringInstanceType(type), &done);
3541 Branch(SmiEqual(LoadStringLengthAsSmi(CAST(source)), SmiConstant(0)), &done,
3546 GotoIfNot(IsEmptyFixedArray(LoadElements(CAST(source))), &call_runtime);
3548 ForEachEnumerableOwnProperty(context, map, CAST(source),
3549 [=](TNode<Name> key, TNode<Object> value) {
3550 SetPropertyInLiteral(context, result, key,
3556 BIND(&call_runtime);
3557 CallRuntime(Runtime::kCopyDataProperties, context, result, source);
3564 void AccessorAssembler::GenerateCloneObjectIC() {
3565 typedef CloneObjectWithVectorDescriptor Descriptor;
3566 TNode<HeapObject> source = CAST(Parameter(Descriptor::kSource));
3567 Node* flags = Parameter(Descriptor::kFlags);
3568 Node* slot = Parameter(Descriptor::kSlot);
3569 Node* vector = Parameter(Descriptor::kVector);
3570 Node* context = Parameter(Descriptor::kContext);
3571 TVARIABLE(MaybeObject, var_handler);
3572 Label if_handler(
this, &var_handler);
3573 Label miss(
this, Label::kDeferred), try_polymorphic(
this, Label::kDeferred),
3574 try_megamorphic(
this, Label::kDeferred);
3576 TNode<Map> source_map = LoadMap(UncheckedCast<HeapObject>(source));
3577 GotoIf(IsDeprecatedMap(source_map), &miss);
3578 TNode<MaybeObject> feedback = TryMonomorphicCase(
3579 slot, vector, source_map, &if_handler, &var_handler, &try_polymorphic);
3583 Comment(
"CloneObjectIC_if_handler");
3587 TNode<Map> result_map = CAST(var_handler.value());
3588 TVARIABLE(Object, var_properties, EmptyFixedArrayConstant());
3589 TVARIABLE(FixedArrayBase, var_elements, EmptyFixedArrayConstant());
3591 Label allocate_object(
this);
3592 GotoIf(IsNullOrUndefined(source), &allocate_object);
3593 CSA_SLOW_ASSERT(
this, IsJSObjectMap(result_map));
3597 TNode<FixedArrayBase> source_elements = LoadElements(CAST(source));
3599 auto flags = ExtractFixedArrayFlag::kAllFixedArraysDontCopyCOW;
3600 var_elements = CAST(CloneFixedArray(source_elements, flags));
3605 TNode<Object> source_properties =
3606 LoadObjectField(source, JSObject::kPropertiesOrHashOffset);
3608 GotoIf(TaggedIsSmi(source_properties), &allocate_object);
3609 GotoIf(IsEmptyFixedArray(source_properties), &allocate_object);
3612 CSA_SLOW_ASSERT(
this, IsPropertyArray(CAST(source_properties)));
3613 TNode<IntPtrT> length = LoadPropertyArrayLength(
3614 UncheckedCast<PropertyArray>(source_properties));
3615 GotoIf(IntPtrEqual(length, IntPtrConstant(0)), &allocate_object);
3617 auto mode = INTPTR_PARAMETERS;
3618 var_properties = CAST(AllocatePropertyArray(length, mode));
3619 FillPropertyArrayWithUndefined(var_properties.value(), IntPtrConstant(0),
3621 CopyPropertyArrayValues(source_properties, var_properties.value(), length,
3622 SKIP_WRITE_BARRIER, mode, DestroySource::kNo);
3625 Goto(&allocate_object);
3626 BIND(&allocate_object);
3627 TNode<JSObject>
object = UncheckedCast<JSObject>(AllocateJSObjectFromMap(
3628 result_map, var_properties.value(), var_elements.value()));
3629 ReturnIf(IsNullOrUndefined(source),
object);
3634 TNode<IntPtrT> source_start =
3635 LoadMapInobjectPropertiesStartInWords(source_map);
3636 TNode<IntPtrT> source_size = LoadMapInstanceSizeInWords(source_map);
3637 TNode<IntPtrT> result_start =
3638 LoadMapInobjectPropertiesStartInWords(result_map);
3639 TNode<IntPtrT> field_offset_difference =
3640 TimesPointerSize(IntPtrSub(result_start, source_start));
3647 const bool may_use_mutable_heap_numbers = !FLAG_unbox_double_fields;
3650 source_start, source_size,
3651 [=](Node* field_index) {
3652 TNode<IntPtrT> field_offset =
3653 TimesPointerSize(UncheckedCast<IntPtrT>(field_index));
3655 if (may_use_mutable_heap_numbers) {
3656 TNode<Object> field = LoadObjectField(source, field_offset);
3657 field = CloneIfMutablePrimitive(field);
3658 TNode<IntPtrT> result_offset =
3659 IntPtrAdd(field_offset, field_offset_difference);
3660 StoreObjectField(
object, result_offset, field);
3663 TNode<IntPtrT> field =
3664 LoadObjectField<IntPtrT>(source, field_offset);
3665 TNode<IntPtrT> result_offset =
3666 IntPtrAdd(field_offset, field_offset_difference);
3667 StoreObjectFieldNoWriteBarrier(
object, result_offset, field);
3670 1, INTPTR_PARAMETERS, IndexAdvanceMode::kPost);
3674 BIND(&try_polymorphic);
3675 TNode<HeapObject> strong_feedback = GetHeapObjectIfStrong(feedback, &miss);
3677 Comment(
"CloneObjectIC_try_polymorphic");
3678 GotoIfNot(IsWeakFixedArrayMap(LoadMap(strong_feedback)), &try_megamorphic);
3679 HandlePolymorphicCase(source_map, CAST(strong_feedback), &if_handler,
3680 &var_handler, &miss, 2);
3683 BIND(&try_megamorphic);
3685 Comment(
"CloneObjectIC_try_megamorphic");
3687 Word32Or(WordEqual(strong_feedback,
3688 LoadRoot(RootIndex::kuninitialized_symbol)),
3689 WordEqual(strong_feedback,
3690 LoadRoot(RootIndex::kmegamorphic_symbol))));
3692 WordEqual(strong_feedback, LoadRoot(RootIndex::kmegamorphic_symbol)),
3694 TailCallBuiltin(Builtins::kCloneObjectIC_Slow, context, source, flags, slot,
3700 Comment(
"CloneObjectIC_miss");
3701 Node* map_or_result = CallRuntime(Runtime::kCloneObjectIC_Miss, context,
3702 source, flags, slot, vector);
3703 var_handler = UncheckedCast<MaybeObject>(map_or_result);
3704 GotoIf(IsMap(map_or_result), &if_handler);
3705 CSA_ASSERT(
this, IsJSObject(map_or_result));
3706 Return(map_or_result);