5 #include "src/ic/handler-configuration.h" 7 #include "src/code-factory.h" 8 #include "src/ic/handler-configuration-inl.h" 9 #include "src/objects/data-handler-inl.h" 10 #include "src/objects/maybe-object.h" 11 #include "src/transitions.h" 18 template <
typename BitField>
19 Handle<Smi> SetBitFieldValue(Isolate* isolate, Handle<Smi> smi_handler,
20 typename BitField::FieldType value) {
21 int config = smi_handler->value();
22 config = BitField::update(config,
true);
23 return handle(Smi::FromInt(config), isolate);
28 template <
typename ICHandler,
bool fill_handler = true>
29 int InitPrototypeChecksImpl(Isolate* isolate, Handle<ICHandler> handler,
30 Handle<Smi>* smi_handler, Handle<Map> receiver_map,
31 Handle<JSReceiver> holder, MaybeObjectHandle data1,
32 MaybeObjectHandle maybe_data2) {
37 if (receiver_map->IsPrimitiveMap() ||
38 receiver_map->is_access_check_needed()) {
39 DCHECK(!receiver_map->IsJSGlobalObjectMap());
47 Handle<Context> native_context = isolate->native_context();
48 handler->set_data2(HeapObjectReference::Weak(*native_context));
51 typedef typename ICHandler::DoAccessCheckOnReceiverBits Bit;
52 *smi_handler = SetBitFieldValue<Bit>(isolate, *smi_handler,
true);
55 }
else if (receiver_map->is_dictionary_map() &&
56 !receiver_map->IsJSGlobalObjectMap()) {
59 typedef typename ICHandler::LookupOnReceiverBits Bit;
60 *smi_handler = SetBitFieldValue<Bit>(isolate, *smi_handler,
true);
64 handler->set_data1(*data1);
66 if (!maybe_data2.is_null()) {
70 if (checks_count == 0) {
71 handler->set_data2(*maybe_data2);
73 DCHECK_EQ(1, checks_count);
74 handler->set_data3(*maybe_data2);
88 template <
typename ICHandler>
89 int GetPrototypeCheckCount(
90 Isolate* isolate, Handle<Smi>* smi_handler, Handle<Map> receiver_map,
91 Handle<JSReceiver> holder, MaybeObjectHandle data1,
92 MaybeObjectHandle maybe_data2 = MaybeObjectHandle()) {
93 DCHECK_NOT_NULL(smi_handler);
94 return InitPrototypeChecksImpl<ICHandler, false>(isolate, Handle<ICHandler>(),
95 smi_handler, receiver_map,
96 holder, data1, maybe_data2);
99 template <
typename ICHandler>
100 void InitPrototypeChecks(Isolate* isolate, Handle<ICHandler> handler,
101 Handle<Map> receiver_map, Handle<JSReceiver> holder,
102 MaybeObjectHandle data1,
103 MaybeObjectHandle maybe_data2 = MaybeObjectHandle()) {
104 InitPrototypeChecksImpl<ICHandler, true>(
105 isolate, handler,
nullptr, receiver_map, holder, data1, maybe_data2);
111 Handle<Object> LoadHandler::LoadFromPrototype(Isolate* isolate,
112 Handle<Map> receiver_map,
113 Handle<JSReceiver> holder,
114 Handle<Smi> smi_handler,
115 MaybeObjectHandle maybe_data1,
116 MaybeObjectHandle maybe_data2) {
117 MaybeObjectHandle data1;
118 if (maybe_data1.is_null()) {
119 data1 = MaybeObjectHandle::Weak(holder);
124 int checks_count = GetPrototypeCheckCount<LoadHandler>(
125 isolate, &smi_handler, receiver_map, holder, data1, maybe_data2);
127 Handle<Object> validity_cell =
128 Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate);
130 int data_count = 1 + checks_count;
131 Handle<LoadHandler> handler = isolate->factory()->NewLoadHandler(data_count);
133 handler->set_smi_handler(*smi_handler);
134 handler->set_validity_cell(*validity_cell);
135 InitPrototypeChecks(isolate, handler, receiver_map, holder, data1,
141 Handle<Object> LoadHandler::LoadFullChain(Isolate* isolate,
142 Handle<Map> receiver_map,
143 const MaybeObjectHandle& holder,
144 Handle<Smi> smi_handler) {
145 Handle<JSReceiver> end;
146 MaybeObjectHandle data1 = holder;
147 int checks_count = GetPrototypeCheckCount<LoadHandler>(
148 isolate, &smi_handler, receiver_map, end, data1);
150 Handle<Object> validity_cell =
151 Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate);
152 if (validity_cell->IsSmi()) {
153 DCHECK_EQ(0, checks_count);
155 if (!LookupOnReceiverBits::decode(smi_handler->value()))
return smi_handler;
158 int data_count = 1 + checks_count;
159 Handle<LoadHandler> handler = isolate->factory()->NewLoadHandler(data_count);
161 handler->set_smi_handler(*smi_handler);
162 handler->set_validity_cell(*validity_cell);
163 InitPrototypeChecks(isolate, handler, receiver_map, end, data1);
168 KeyedAccessLoadMode LoadHandler::GetKeyedAccessLoadMode(MaybeObject handler) {
169 DisallowHeapAllocation no_gc;
170 if (handler->IsSmi()) {
171 int const raw_handler = handler.ToSmi().value();
172 Kind
const kind = KindBits::decode(raw_handler);
173 if ((kind == kElement || kind == kIndexedString) &&
174 AllowOutOfBoundsBits::decode(raw_handler)) {
175 return LOAD_IGNORE_OUT_OF_BOUNDS;
178 return STANDARD_LOAD;
182 Handle<Object> StoreHandler::StoreElementTransition(
183 Isolate* isolate, Handle<Map> receiver_map, Handle<Map> transition,
184 KeyedAccessStoreMode store_mode) {
186 CodeFactory::ElementsTransitionAndStore(isolate, store_mode).code();
187 Handle<Object> validity_cell =
188 Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate);
189 Handle<StoreHandler> handler = isolate->factory()->NewStoreHandler(1);
190 handler->set_smi_handler(*stub);
191 handler->set_validity_cell(*validity_cell);
192 handler->set_data1(HeapObjectReference::Weak(*transition));
196 MaybeObjectHandle StoreHandler::StoreTransition(Isolate* isolate,
197 Handle<Map> transition_map) {
198 bool is_dictionary_map = transition_map->is_dictionary_map();
200 if (!is_dictionary_map) {
201 int descriptor = transition_map->LastAdded();
202 Handle<DescriptorArray> descriptors(transition_map->instance_descriptors(),
204 PropertyDetails details = descriptors->GetDetails(descriptor);
205 if (descriptors->GetKey(descriptor)->IsPrivate()) {
206 DCHECK_EQ(DONT_ENUM, details.attributes());
208 DCHECK_EQ(NONE, details.attributes());
210 Representation representation = details.representation();
211 DCHECK(!representation.IsNone());
215 DCHECK(!transition_map->is_access_check_needed());
218 Handle<Object> validity_cell;
219 if (is_dictionary_map || !transition_map->IsPrototypeValidityCellValid()) {
221 Map::GetOrCreatePrototypeChainValidityCell(transition_map, isolate);
224 if (is_dictionary_map) {
225 DCHECK(!transition_map->IsJSGlobalObjectMap());
226 Handle<StoreHandler> handler = isolate->factory()->NewStoreHandler(0);
228 int config = KindBits::encode(kNormal) | LookupOnReceiverBits::encode(
true);
229 handler->set_smi_handler(Smi::FromInt(config));
230 handler->set_validity_cell(*validity_cell);
231 return MaybeObjectHandle(handler);
235 if (!validity_cell.is_null()) {
236 transition_map->set_prototype_validity_cell(*validity_cell);
238 return MaybeObjectHandle::Weak(transition_map);
243 Handle<Object> StoreHandler::StoreThroughPrototype(
244 Isolate* isolate, Handle<Map> receiver_map, Handle<JSReceiver> holder,
245 Handle<Smi> smi_handler, MaybeObjectHandle maybe_data1,
246 MaybeObjectHandle maybe_data2) {
247 MaybeObjectHandle data1;
248 if (maybe_data1.is_null()) {
249 data1 = MaybeObjectHandle::Weak(holder);
254 int checks_count = GetPrototypeCheckCount<StoreHandler>(
255 isolate, &smi_handler, receiver_map, holder, data1, maybe_data2);
257 Handle<Object> validity_cell =
258 Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate);
259 DCHECK_IMPLIES(validity_cell->IsSmi(), checks_count == 0);
261 int data_count = 1 + checks_count;
262 Handle<StoreHandler> handler =
263 isolate->factory()->NewStoreHandler(data_count);
265 handler->set_smi_handler(*smi_handler);
266 handler->set_validity_cell(*validity_cell);
267 InitPrototypeChecks(isolate, handler, receiver_map, holder, data1,
273 MaybeObjectHandle StoreHandler::StoreGlobal(Handle<PropertyCell> cell) {
274 return MaybeObjectHandle::Weak(cell);
278 Handle<Object> StoreHandler::StoreProxy(Isolate* isolate,
279 Handle<Map> receiver_map,
280 Handle<JSProxy> proxy,
281 Handle<JSReceiver> receiver) {
282 Handle<Smi> smi_handler = StoreProxy(isolate);
283 if (receiver.is_identical_to(proxy))
return smi_handler;
284 return StoreThroughPrototype(isolate, receiver_map, proxy, smi_handler,
285 MaybeObjectHandle::Weak(proxy));