OLD | NEW |
1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/ic/accessor-assembler.h" | 5 #include "src/ic/accessor-assembler.h" |
6 | 6 |
7 #include "src/code-factory.h" | 7 #include "src/code-factory.h" |
8 #include "src/code-stubs.h" | 8 #include "src/code-stubs.h" |
9 #include "src/ic/handler-configuration.h" | 9 #include "src/ic/handler-configuration.h" |
10 #include "src/ic/stub-cache.h" | 10 #include "src/ic/stub-cache.h" |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
134 }, | 134 }, |
135 kEntrySize, INTPTR_PARAMETERS, IndexAdvanceMode::kPost); | 135 kEntrySize, INTPTR_PARAMETERS, IndexAdvanceMode::kPost); |
136 // The loop falls through if no handler was found. | 136 // The loop falls through if no handler was found. |
137 Goto(if_miss); | 137 Goto(if_miss); |
138 } | 138 } |
139 | 139 |
140 void AccessorAssembler::HandleLoadICHandlerCase( | 140 void AccessorAssembler::HandleLoadICHandlerCase( |
141 const LoadICParameters* p, Node* handler, Label* miss, | 141 const LoadICParameters* p, Node* handler, Label* miss, |
142 ElementSupport support_elements) { | 142 ElementSupport support_elements) { |
143 Comment("have_handler"); | 143 Comment("have_handler"); |
| 144 ExitPoint direct_exit(this); |
| 145 |
144 Variable var_holder(this, MachineRepresentation::kTagged); | 146 Variable var_holder(this, MachineRepresentation::kTagged); |
145 var_holder.Bind(p->receiver); | 147 var_holder.Bind(p->receiver); |
146 Variable var_smi_handler(this, MachineRepresentation::kTagged); | 148 Variable var_smi_handler(this, MachineRepresentation::kTagged); |
147 var_smi_handler.Bind(handler); | 149 var_smi_handler.Bind(handler); |
148 | 150 |
149 Variable* vars[] = {&var_holder, &var_smi_handler}; | 151 Variable* vars[] = {&var_holder, &var_smi_handler}; |
150 Label if_smi_handler(this, 2, vars); | 152 Label if_smi_handler(this, 2, vars); |
151 Label try_proto_handler(this), call_handler(this); | 153 Label try_proto_handler(this), call_handler(this); |
152 | 154 |
153 Branch(TaggedIsSmi(handler), &if_smi_handler, &try_proto_handler); | 155 Branch(TaggedIsSmi(handler), &if_smi_handler, &try_proto_handler); |
154 | 156 |
155 // |handler| is a Smi, encoding what to do. See SmiHandler methods | 157 // |handler| is a Smi, encoding what to do. See SmiHandler methods |
156 // for the encoding format. | 158 // for the encoding format. |
157 Bind(&if_smi_handler); | 159 Bind(&if_smi_handler); |
158 { | 160 { |
159 HandleLoadICSmiHandlerCase(p, var_holder.value(), var_smi_handler.value(), | 161 HandleLoadICSmiHandlerCase(p, var_holder.value(), var_smi_handler.value(), |
160 miss, support_elements); | 162 miss, &direct_exit, support_elements); |
161 } | 163 } |
162 | 164 |
163 Bind(&try_proto_handler); | 165 Bind(&try_proto_handler); |
164 { | 166 { |
165 GotoIf(IsCodeMap(LoadMap(handler)), &call_handler); | 167 GotoIf(IsCodeMap(LoadMap(handler)), &call_handler); |
166 HandleLoadICProtoHandlerCase(p, handler, &var_holder, &var_smi_handler, | 168 HandleLoadICProtoHandlerCase(p, handler, &var_holder, &var_smi_handler, |
167 &if_smi_handler, miss, false); | 169 &if_smi_handler, miss, &direct_exit, false); |
168 } | 170 } |
169 | 171 |
170 Bind(&call_handler); | 172 Bind(&call_handler); |
171 { | 173 { |
172 typedef LoadWithVectorDescriptor Descriptor; | 174 typedef LoadWithVectorDescriptor Descriptor; |
173 TailCallStub(Descriptor(isolate()), handler, p->context, p->receiver, | 175 TailCallStub(Descriptor(isolate()), handler, p->context, p->receiver, |
174 p->name, p->slot, p->vector); | 176 p->name, p->slot, p->vector); |
175 } | 177 } |
176 } | 178 } |
177 | 179 |
178 void AccessorAssembler::HandleLoadICSmiHandlerCase( | 180 void AccessorAssembler::HandleLoadICSmiHandlerCase( |
179 const LoadICParameters* p, Node* holder, Node* smi_handler, Label* miss, | 181 const LoadICParameters* p, Node* holder, Node* smi_handler, Label* miss, |
180 ElementSupport support_elements) { | 182 ExitPoint* exit_point, ElementSupport support_elements) { |
181 Variable var_double_value(this, MachineRepresentation::kFloat64); | 183 Variable var_double_value(this, MachineRepresentation::kFloat64); |
182 Label rebox_double(this, &var_double_value); | 184 Label rebox_double(this, &var_double_value); |
183 | 185 |
184 Node* handler_word = SmiUntag(smi_handler); | 186 Node* handler_word = SmiUntag(smi_handler); |
185 Node* handler_kind = DecodeWord<LoadHandler::KindBits>(handler_word); | 187 Node* handler_kind = DecodeWord<LoadHandler::KindBits>(handler_word); |
186 if (support_elements == kSupportElements) { | 188 if (support_elements == kSupportElements) { |
187 Label property(this); | 189 Label property(this); |
188 GotoUnless( | 190 GotoUnless( |
189 WordEqual(handler_kind, IntPtrConstant(LoadHandler::kForElements)), | 191 WordEqual(handler_kind, IntPtrConstant(LoadHandler::kForElements)), |
190 &property); | 192 &property); |
191 | 193 |
192 Comment("element_load"); | 194 Comment("element_load"); |
193 Node* intptr_index = TryToIntptr(p->name, miss); | 195 Node* intptr_index = TryToIntptr(p->name, miss); |
194 Node* elements = LoadElements(holder); | 196 Node* elements = LoadElements(holder); |
195 Node* is_jsarray_condition = | 197 Node* is_jsarray_condition = |
196 IsSetWord<LoadHandler::IsJsArrayBits>(handler_word); | 198 IsSetWord<LoadHandler::IsJsArrayBits>(handler_word); |
197 Node* elements_kind = | 199 Node* elements_kind = |
198 DecodeWord32FromWord<LoadHandler::ElementsKindBits>(handler_word); | 200 DecodeWord32FromWord<LoadHandler::ElementsKindBits>(handler_word); |
199 Label if_hole(this), unimplemented_elements_kind(this); | 201 Label if_hole(this), unimplemented_elements_kind(this); |
200 Label* out_of_bounds = miss; | 202 Label* out_of_bounds = miss; |
201 EmitElementLoad(holder, elements, elements_kind, intptr_index, | 203 EmitElementLoad(holder, elements, elements_kind, intptr_index, |
202 is_jsarray_condition, &if_hole, &rebox_double, | 204 is_jsarray_condition, &if_hole, &rebox_double, |
203 &var_double_value, &unimplemented_elements_kind, | 205 &var_double_value, &unimplemented_elements_kind, |
204 out_of_bounds, miss); | 206 out_of_bounds, miss, exit_point); |
205 | 207 |
206 Bind(&unimplemented_elements_kind); | 208 Bind(&unimplemented_elements_kind); |
207 { | 209 { |
208 // Smi handlers should only be installed for supported elements kinds. | 210 // Smi handlers should only be installed for supported elements kinds. |
209 // Crash if we get here. | 211 // Crash if we get here. |
210 DebugBreak(); | 212 DebugBreak(); |
211 Goto(miss); | 213 Goto(miss); |
212 } | 214 } |
213 | 215 |
214 Bind(&if_hole); | 216 Bind(&if_hole); |
215 { | 217 { |
216 Comment("convert hole"); | 218 Comment("convert hole"); |
217 GotoUnless(IsSetWord<LoadHandler::ConvertHoleBits>(handler_word), miss); | 219 GotoUnless(IsSetWord<LoadHandler::ConvertHoleBits>(handler_word), miss); |
218 Node* protector_cell = LoadRoot(Heap::kArrayProtectorRootIndex); | 220 Node* protector_cell = LoadRoot(Heap::kArrayProtectorRootIndex); |
219 DCHECK(isolate()->heap()->array_protector()->IsPropertyCell()); | 221 DCHECK(isolate()->heap()->array_protector()->IsPropertyCell()); |
220 GotoUnless( | 222 GotoUnless( |
221 WordEqual(LoadObjectField(protector_cell, PropertyCell::kValueOffset), | 223 WordEqual(LoadObjectField(protector_cell, PropertyCell::kValueOffset), |
222 SmiConstant(Smi::FromInt(Isolate::kProtectorValid))), | 224 SmiConstant(Smi::FromInt(Isolate::kProtectorValid))), |
223 miss); | 225 miss); |
224 Return(UndefinedConstant()); | 226 exit_point->Return(UndefinedConstant()); |
225 } | 227 } |
226 | 228 |
227 Bind(&property); | 229 Bind(&property); |
228 Comment("property_load"); | 230 Comment("property_load"); |
229 } | 231 } |
230 | 232 |
231 Label constant(this), field(this); | 233 Label constant(this), field(this); |
232 Branch(WordEqual(handler_kind, IntPtrConstant(LoadHandler::kForFields)), | 234 Branch(WordEqual(handler_kind, IntPtrConstant(LoadHandler::kForFields)), |
233 &field, &constant); | 235 &field, &constant); |
234 | 236 |
235 Bind(&field); | 237 Bind(&field); |
236 { | 238 { |
237 Comment("field_load"); | 239 Comment("field_load"); |
238 Node* offset = DecodeWord<LoadHandler::FieldOffsetBits>(handler_word); | 240 Node* offset = DecodeWord<LoadHandler::FieldOffsetBits>(handler_word); |
239 | 241 |
240 Label inobject(this), out_of_object(this); | 242 Label inobject(this), out_of_object(this); |
241 Branch(IsSetWord<LoadHandler::IsInobjectBits>(handler_word), &inobject, | 243 Branch(IsSetWord<LoadHandler::IsInobjectBits>(handler_word), &inobject, |
242 &out_of_object); | 244 &out_of_object); |
243 | 245 |
244 Bind(&inobject); | 246 Bind(&inobject); |
245 { | 247 { |
246 Label is_double(this); | 248 Label is_double(this); |
247 GotoIf(IsSetWord<LoadHandler::IsDoubleBits>(handler_word), &is_double); | 249 GotoIf(IsSetWord<LoadHandler::IsDoubleBits>(handler_word), &is_double); |
248 Return(LoadObjectField(holder, offset)); | 250 exit_point->Return(LoadObjectField(holder, offset)); |
249 | 251 |
250 Bind(&is_double); | 252 Bind(&is_double); |
251 if (FLAG_unbox_double_fields) { | 253 if (FLAG_unbox_double_fields) { |
252 var_double_value.Bind( | 254 var_double_value.Bind( |
253 LoadObjectField(holder, offset, MachineType::Float64())); | 255 LoadObjectField(holder, offset, MachineType::Float64())); |
254 } else { | 256 } else { |
255 Node* mutable_heap_number = LoadObjectField(holder, offset); | 257 Node* mutable_heap_number = LoadObjectField(holder, offset); |
256 var_double_value.Bind(LoadHeapNumberValue(mutable_heap_number)); | 258 var_double_value.Bind(LoadHeapNumberValue(mutable_heap_number)); |
257 } | 259 } |
258 Goto(&rebox_double); | 260 Goto(&rebox_double); |
259 } | 261 } |
260 | 262 |
261 Bind(&out_of_object); | 263 Bind(&out_of_object); |
262 { | 264 { |
263 Label is_double(this); | 265 Label is_double(this); |
264 Node* properties = LoadProperties(holder); | 266 Node* properties = LoadProperties(holder); |
265 Node* value = LoadObjectField(properties, offset); | 267 Node* value = LoadObjectField(properties, offset); |
266 GotoIf(IsSetWord<LoadHandler::IsDoubleBits>(handler_word), &is_double); | 268 GotoIf(IsSetWord<LoadHandler::IsDoubleBits>(handler_word), &is_double); |
267 Return(value); | 269 exit_point->Return(value); |
268 | 270 |
269 Bind(&is_double); | 271 Bind(&is_double); |
270 var_double_value.Bind(LoadHeapNumberValue(value)); | 272 var_double_value.Bind(LoadHeapNumberValue(value)); |
271 Goto(&rebox_double); | 273 Goto(&rebox_double); |
272 } | 274 } |
273 | 275 |
274 Bind(&rebox_double); | 276 Bind(&rebox_double); |
275 Return(AllocateHeapNumberWithValue(var_double_value.value())); | 277 exit_point->Return(AllocateHeapNumberWithValue(var_double_value.value())); |
276 } | 278 } |
277 | 279 |
278 Bind(&constant); | 280 Bind(&constant); |
279 { | 281 { |
280 Comment("constant_load"); | 282 Comment("constant_load"); |
281 Node* descriptors = LoadMapDescriptors(LoadMap(holder)); | 283 Node* descriptors = LoadMapDescriptors(LoadMap(holder)); |
282 Node* descriptor = | 284 Node* descriptor = |
283 DecodeWord<LoadHandler::DescriptorValueIndexBits>(handler_word); | 285 DecodeWord<LoadHandler::DescriptorValueIndexBits>(handler_word); |
284 CSA_ASSERT(this, | 286 CSA_ASSERT(this, |
285 UintPtrLessThan(descriptor, | 287 UintPtrLessThan(descriptor, |
286 LoadAndUntagFixedArrayBaseLength(descriptors))); | 288 LoadAndUntagFixedArrayBaseLength(descriptors))); |
287 Node* value = LoadFixedArrayElement(descriptors, descriptor); | 289 Node* value = LoadFixedArrayElement(descriptors, descriptor); |
288 | 290 |
289 Label if_accessor_info(this); | 291 Label if_accessor_info(this); |
290 GotoIf(IsSetWord<LoadHandler::IsAccessorInfoBits>(handler_word), | 292 GotoIf(IsSetWord<LoadHandler::IsAccessorInfoBits>(handler_word), |
291 &if_accessor_info); | 293 &if_accessor_info); |
292 Return(value); | 294 exit_point->Return(value); |
293 | 295 |
294 Bind(&if_accessor_info); | 296 Bind(&if_accessor_info); |
295 Callable callable = CodeFactory::ApiGetter(isolate()); | 297 Callable callable = CodeFactory::ApiGetter(isolate()); |
296 TailCallStub(callable, p->context, p->receiver, holder, value); | 298 exit_point->ReturnCallStub(callable, p->context, p->receiver, holder, |
| 299 value); |
297 } | 300 } |
298 } | 301 } |
299 | 302 |
300 void AccessorAssembler::HandleLoadICProtoHandlerCase( | 303 void AccessorAssembler::HandleLoadICProtoHandlerCase( |
301 const LoadICParameters* p, Node* handler, Variable* var_holder, | 304 const LoadICParameters* p, Node* handler, Variable* var_holder, |
302 Variable* var_smi_handler, Label* if_smi_handler, Label* miss, | 305 Variable* var_smi_handler, Label* if_smi_handler, Label* miss, |
303 bool throw_reference_error_if_nonexistent) { | 306 ExitPoint* exit_point, bool throw_reference_error_if_nonexistent) { |
304 DCHECK_EQ(MachineRepresentation::kTagged, var_holder->rep()); | 307 DCHECK_EQ(MachineRepresentation::kTagged, var_holder->rep()); |
305 DCHECK_EQ(MachineRepresentation::kTagged, var_smi_handler->rep()); | 308 DCHECK_EQ(MachineRepresentation::kTagged, var_smi_handler->rep()); |
306 | 309 |
307 // IC dispatchers rely on these assumptions to be held. | 310 // IC dispatchers rely on these assumptions to be held. |
308 STATIC_ASSERT(FixedArray::kLengthOffset == LoadHandler::kHolderCellOffset); | 311 STATIC_ASSERT(FixedArray::kLengthOffset == LoadHandler::kHolderCellOffset); |
309 DCHECK_EQ(FixedArray::OffsetOfElementAt(LoadHandler::kSmiHandlerIndex), | 312 DCHECK_EQ(FixedArray::OffsetOfElementAt(LoadHandler::kSmiHandlerIndex), |
310 LoadHandler::kSmiHandlerOffset); | 313 LoadHandler::kSmiHandlerOffset); |
311 DCHECK_EQ(FixedArray::OffsetOfElementAt(LoadHandler::kValidityCellIndex), | 314 DCHECK_EQ(FixedArray::OffsetOfElementAt(LoadHandler::kValidityCellIndex), |
312 LoadHandler::kValidityCellOffset); | 315 LoadHandler::kValidityCellOffset); |
313 | 316 |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
345 LoadObjectField(handler, LoadHandler::kHolderCellOffset); | 348 LoadObjectField(handler, LoadHandler::kHolderCellOffset); |
346 Label array_handler(this), tuple_handler(this); | 349 Label array_handler(this), tuple_handler(this); |
347 Branch(TaggedIsSmi(maybe_holder_cell), &array_handler, &tuple_handler); | 350 Branch(TaggedIsSmi(maybe_holder_cell), &array_handler, &tuple_handler); |
348 | 351 |
349 Bind(&tuple_handler); | 352 Bind(&tuple_handler); |
350 { | 353 { |
351 Label load_existent(this); | 354 Label load_existent(this); |
352 GotoIf(WordNotEqual(maybe_holder_cell, NullConstant()), &load_existent); | 355 GotoIf(WordNotEqual(maybe_holder_cell, NullConstant()), &load_existent); |
353 // This is a handler for a load of a non-existent value. | 356 // This is a handler for a load of a non-existent value. |
354 if (throw_reference_error_if_nonexistent) { | 357 if (throw_reference_error_if_nonexistent) { |
355 TailCallRuntime(Runtime::kThrowReferenceError, p->context, p->name); | 358 exit_point->ReturnCallRuntime(Runtime::kThrowReferenceError, p->context, |
| 359 p->name); |
356 } else { | 360 } else { |
357 Return(UndefinedConstant()); | 361 exit_point->Return(UndefinedConstant()); |
358 } | 362 } |
359 | 363 |
360 Bind(&load_existent); | 364 Bind(&load_existent); |
361 Node* holder = LoadWeakCellValue(maybe_holder_cell); | 365 Node* holder = LoadWeakCellValue(maybe_holder_cell); |
362 // The |holder| is guaranteed to be alive at this point since we passed | 366 // The |holder| is guaranteed to be alive at this point since we passed |
363 // both the receiver map check and the validity cell check. | 367 // both the receiver map check and the validity cell check. |
364 CSA_ASSERT(this, WordNotEqual(holder, IntPtrConstant(0))); | 368 CSA_ASSERT(this, WordNotEqual(holder, IntPtrConstant(0))); |
365 | 369 |
366 var_holder->Bind(holder); | 370 var_holder->Bind(holder); |
367 var_smi_handler->Bind(smi_handler); | 371 var_smi_handler->Bind(smi_handler); |
368 Goto(if_smi_handler); | 372 Goto(if_smi_handler); |
369 } | 373 } |
370 | 374 |
371 Bind(&array_handler); | 375 Bind(&array_handler); |
372 { | 376 { |
373 TailCallStub(CodeFactory::LoadICProtoArray( | 377 exit_point->ReturnCallStub( |
374 isolate(), throw_reference_error_if_nonexistent), | 378 CodeFactory::LoadICProtoArray(isolate(), |
375 p->context, p->receiver, p->name, p->slot, p->vector, handler); | 379 throw_reference_error_if_nonexistent), |
| 380 p->context, p->receiver, p->name, p->slot, p->vector, handler); |
376 } | 381 } |
377 } | 382 } |
378 | 383 |
379 Node* AccessorAssembler::EmitLoadICProtoArrayCheck( | 384 Node* AccessorAssembler::EmitLoadICProtoArrayCheck( |
380 const LoadICParameters* p, Node* handler, Node* handler_length, | 385 const LoadICParameters* p, Node* handler, Node* handler_length, |
381 Node* handler_flags, Label* miss, | 386 Node* handler_flags, Label* miss, |
382 bool throw_reference_error_if_nonexistent) { | 387 bool throw_reference_error_if_nonexistent) { |
383 Variable start_index(this, MachineType::PointerRepresentation()); | 388 Variable start_index(this, MachineType::PointerRepresentation()); |
384 start_index.Bind(IntPtrConstant(LoadHandler::kFirstPrototypeIndex)); | 389 start_index.Bind(IntPtrConstant(LoadHandler::kFirstPrototypeIndex)); |
385 | 390 |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
433 Node* holder = LoadWeakCellValue(maybe_holder_cell); | 438 Node* holder = LoadWeakCellValue(maybe_holder_cell); |
434 // The |holder| is guaranteed to be alive at this point since we passed | 439 // The |holder| is guaranteed to be alive at this point since we passed |
435 // the receiver map check, the validity cell check and the prototype chain | 440 // the receiver map check, the validity cell check and the prototype chain |
436 // check. | 441 // check. |
437 CSA_ASSERT(this, WordNotEqual(holder, IntPtrConstant(0))); | 442 CSA_ASSERT(this, WordNotEqual(holder, IntPtrConstant(0))); |
438 return holder; | 443 return holder; |
439 } | 444 } |
440 | 445 |
441 void AccessorAssembler::HandleLoadGlobalICHandlerCase( | 446 void AccessorAssembler::HandleLoadGlobalICHandlerCase( |
442 const LoadICParameters* pp, Node* handler, Label* miss, | 447 const LoadICParameters* pp, Node* handler, Label* miss, |
443 bool throw_reference_error_if_nonexistent) { | 448 ExitPoint* exit_point, bool throw_reference_error_if_nonexistent) { |
444 LoadICParameters p = *pp; | 449 LoadICParameters p = *pp; |
445 DCHECK_NULL(p.receiver); | 450 DCHECK_NULL(p.receiver); |
446 Node* native_context = LoadNativeContext(p.context); | 451 Node* native_context = LoadNativeContext(p.context); |
447 p.receiver = LoadContextElement(native_context, Context::EXTENSION_INDEX); | 452 p.receiver = LoadContextElement(native_context, Context::EXTENSION_INDEX); |
448 | 453 |
449 Variable var_holder(this, MachineRepresentation::kTagged); | 454 Variable var_holder(this, MachineRepresentation::kTagged); |
450 Variable var_smi_handler(this, MachineRepresentation::kTagged); | 455 Variable var_smi_handler(this, MachineRepresentation::kTagged); |
451 Label if_smi_handler(this); | 456 Label if_smi_handler(this); |
452 HandleLoadICProtoHandlerCase(&p, handler, &var_holder, &var_smi_handler, | 457 HandleLoadICProtoHandlerCase(&p, handler, &var_holder, &var_smi_handler, |
453 &if_smi_handler, miss, | 458 &if_smi_handler, miss, exit_point, |
454 throw_reference_error_if_nonexistent); | 459 throw_reference_error_if_nonexistent); |
455 Bind(&if_smi_handler); | 460 Bind(&if_smi_handler); |
456 HandleLoadICSmiHandlerCase(&p, var_holder.value(), var_smi_handler.value(), | 461 HandleLoadICSmiHandlerCase(&p, var_holder.value(), var_smi_handler.value(), |
457 miss, kOnlyProperties); | 462 miss, exit_point, kOnlyProperties); |
458 } | 463 } |
459 | 464 |
460 void AccessorAssembler::HandleStoreICHandlerCase( | 465 void AccessorAssembler::HandleStoreICHandlerCase( |
461 const StoreICParameters* p, Node* handler, Label* miss, | 466 const StoreICParameters* p, Node* handler, Label* miss, |
462 ElementSupport support_elements) { | 467 ElementSupport support_elements) { |
463 Label if_smi_handler(this), if_nonsmi_handler(this); | 468 Label if_smi_handler(this), if_nonsmi_handler(this); |
464 Label if_proto_handler(this), if_element_handler(this), call_handler(this); | 469 Label if_proto_handler(this), if_element_handler(this), call_handler(this); |
465 | 470 |
466 Branch(TaggedIsSmi(handler), &if_smi_handler, &if_nonsmi_handler); | 471 Branch(TaggedIsSmi(handler), &if_smi_handler, &if_nonsmi_handler); |
467 | 472 |
(...skipping 381 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
849 } | 854 } |
850 Bind(&if_array); | 855 Bind(&if_array); |
851 { | 856 { |
852 var_length.Bind(SmiUntag(LoadJSArrayLength(object))); | 857 var_length.Bind(SmiUntag(LoadJSArrayLength(object))); |
853 Goto(&length_loaded); | 858 Goto(&length_loaded); |
854 } | 859 } |
855 Bind(&length_loaded); | 860 Bind(&length_loaded); |
856 GotoUnless(UintPtrLessThan(intptr_index, var_length.value()), miss); | 861 GotoUnless(UintPtrLessThan(intptr_index, var_length.value()), miss); |
857 } | 862 } |
858 | 863 |
859 void AccessorAssembler::EmitElementLoad(Node* object, Node* elements, | 864 void AccessorAssembler::EmitElementLoad( |
860 Node* elements_kind, Node* intptr_index, | 865 Node* object, Node* elements, Node* elements_kind, Node* intptr_index, |
861 Node* is_jsarray_condition, | 866 Node* is_jsarray_condition, Label* if_hole, Label* rebox_double, |
862 Label* if_hole, Label* rebox_double, | 867 Variable* var_double_value, Label* unimplemented_elements_kind, |
863 Variable* var_double_value, | 868 Label* out_of_bounds, Label* miss, ExitPoint* exit_point) { |
864 Label* unimplemented_elements_kind, | |
865 Label* out_of_bounds, Label* miss) { | |
866 Label if_typed_array(this), if_fast_packed(this), if_fast_holey(this), | 869 Label if_typed_array(this), if_fast_packed(this), if_fast_holey(this), |
867 if_fast_double(this), if_fast_holey_double(this), if_nonfast(this), | 870 if_fast_double(this), if_fast_holey_double(this), if_nonfast(this), |
868 if_dictionary(this); | 871 if_dictionary(this); |
869 GotoIf( | 872 GotoIf( |
870 Int32GreaterThan(elements_kind, Int32Constant(LAST_FAST_ELEMENTS_KIND)), | 873 Int32GreaterThan(elements_kind, Int32Constant(LAST_FAST_ELEMENTS_KIND)), |
871 &if_nonfast); | 874 &if_nonfast); |
872 | 875 |
873 EmitFastElementsBoundsCheck(object, elements, intptr_index, | 876 EmitFastElementsBoundsCheck(object, elements, intptr_index, |
874 is_jsarray_condition, out_of_bounds); | 877 is_jsarray_condition, out_of_bounds); |
875 int32_t kinds[] = {// Handled by if_fast_packed. | 878 int32_t kinds[] = {// Handled by if_fast_packed. |
(...skipping 11 matching lines...) Expand all Loading... |
887 // FAST_DOUBLE_ELEMENTS | 890 // FAST_DOUBLE_ELEMENTS |
888 &if_fast_double, | 891 &if_fast_double, |
889 // FAST_HOLEY_DOUBLE_ELEMENTS | 892 // FAST_HOLEY_DOUBLE_ELEMENTS |
890 &if_fast_holey_double}; | 893 &if_fast_holey_double}; |
891 Switch(elements_kind, unimplemented_elements_kind, kinds, labels, | 894 Switch(elements_kind, unimplemented_elements_kind, kinds, labels, |
892 arraysize(kinds)); | 895 arraysize(kinds)); |
893 | 896 |
894 Bind(&if_fast_packed); | 897 Bind(&if_fast_packed); |
895 { | 898 { |
896 Comment("fast packed elements"); | 899 Comment("fast packed elements"); |
897 Return(LoadFixedArrayElement(elements, intptr_index)); | 900 exit_point->Return(LoadFixedArrayElement(elements, intptr_index)); |
898 } | 901 } |
899 | 902 |
900 Bind(&if_fast_holey); | 903 Bind(&if_fast_holey); |
901 { | 904 { |
902 Comment("fast holey elements"); | 905 Comment("fast holey elements"); |
903 Node* element = LoadFixedArrayElement(elements, intptr_index); | 906 Node* element = LoadFixedArrayElement(elements, intptr_index); |
904 GotoIf(WordEqual(element, TheHoleConstant()), if_hole); | 907 GotoIf(WordEqual(element, TheHoleConstant()), if_hole); |
905 Return(element); | 908 exit_point->Return(element); |
906 } | 909 } |
907 | 910 |
908 Bind(&if_fast_double); | 911 Bind(&if_fast_double); |
909 { | 912 { |
910 Comment("packed double elements"); | 913 Comment("packed double elements"); |
911 var_double_value->Bind(LoadFixedDoubleArrayElement(elements, intptr_index, | 914 var_double_value->Bind(LoadFixedDoubleArrayElement(elements, intptr_index, |
912 MachineType::Float64())); | 915 MachineType::Float64())); |
913 Goto(rebox_double); | 916 Goto(rebox_double); |
914 } | 917 } |
915 | 918 |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
947 // Check that the value is a data property. | 950 // Check that the value is a data property. |
948 Node* details_index = EntryToIndex<SeededNumberDictionary>( | 951 Node* details_index = EntryToIndex<SeededNumberDictionary>( |
949 var_entry.value(), SeededNumberDictionary::kEntryDetailsIndex); | 952 var_entry.value(), SeededNumberDictionary::kEntryDetailsIndex); |
950 Node* details = SmiToWord32(LoadFixedArrayElement(elements, details_index)); | 953 Node* details = SmiToWord32(LoadFixedArrayElement(elements, details_index)); |
951 Node* kind = DecodeWord32<PropertyDetails::KindField>(details); | 954 Node* kind = DecodeWord32<PropertyDetails::KindField>(details); |
952 // TODO(jkummerow): Support accessors without missing? | 955 // TODO(jkummerow): Support accessors without missing? |
953 GotoUnless(Word32Equal(kind, Int32Constant(kData)), miss); | 956 GotoUnless(Word32Equal(kind, Int32Constant(kData)), miss); |
954 // Finally, load the value. | 957 // Finally, load the value. |
955 Node* value_index = EntryToIndex<SeededNumberDictionary>( | 958 Node* value_index = EntryToIndex<SeededNumberDictionary>( |
956 var_entry.value(), SeededNumberDictionary::kEntryValueIndex); | 959 var_entry.value(), SeededNumberDictionary::kEntryValueIndex); |
957 Return(LoadFixedArrayElement(elements, value_index)); | 960 exit_point->Return(LoadFixedArrayElement(elements, value_index)); |
958 } | 961 } |
959 | 962 |
960 Bind(&if_typed_array); | 963 Bind(&if_typed_array); |
961 { | 964 { |
962 Comment("typed elements"); | 965 Comment("typed elements"); |
963 // Check if buffer has been neutered. | 966 // Check if buffer has been neutered. |
964 Node* buffer = LoadObjectField(object, JSArrayBufferView::kBufferOffset); | 967 Node* buffer = LoadObjectField(object, JSArrayBufferView::kBufferOffset); |
965 GotoIf(IsDetachedBuffer(buffer), miss); | 968 GotoIf(IsDetachedBuffer(buffer), miss); |
966 | 969 |
967 // Bounds check. | 970 // Bounds check. |
(...skipping 25 matching lines...) Expand all Loading... |
993 LAST_FIXED_TYPED_ARRAY_ELEMENTS_KIND - | 996 LAST_FIXED_TYPED_ARRAY_ELEMENTS_KIND - |
994 FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND + 1; | 997 FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND + 1; |
995 DCHECK_EQ(kTypedElementsKindCount, arraysize(elements_kinds)); | 998 DCHECK_EQ(kTypedElementsKindCount, arraysize(elements_kinds)); |
996 DCHECK_EQ(kTypedElementsKindCount, arraysize(elements_kind_labels)); | 999 DCHECK_EQ(kTypedElementsKindCount, arraysize(elements_kind_labels)); |
997 Switch(elements_kind, miss, elements_kinds, elements_kind_labels, | 1000 Switch(elements_kind, miss, elements_kinds, elements_kind_labels, |
998 kTypedElementsKindCount); | 1001 kTypedElementsKindCount); |
999 Bind(&uint8_elements); | 1002 Bind(&uint8_elements); |
1000 { | 1003 { |
1001 Comment("UINT8_ELEMENTS"); // Handles UINT8_CLAMPED_ELEMENTS too. | 1004 Comment("UINT8_ELEMENTS"); // Handles UINT8_CLAMPED_ELEMENTS too. |
1002 Node* element = Load(MachineType::Uint8(), backing_store, intptr_index); | 1005 Node* element = Load(MachineType::Uint8(), backing_store, intptr_index); |
1003 Return(SmiFromWord32(element)); | 1006 exit_point->Return(SmiFromWord32(element)); |
1004 } | 1007 } |
1005 Bind(&int8_elements); | 1008 Bind(&int8_elements); |
1006 { | 1009 { |
1007 Comment("INT8_ELEMENTS"); | 1010 Comment("INT8_ELEMENTS"); |
1008 Node* element = Load(MachineType::Int8(), backing_store, intptr_index); | 1011 Node* element = Load(MachineType::Int8(), backing_store, intptr_index); |
1009 Return(SmiFromWord32(element)); | 1012 exit_point->Return(SmiFromWord32(element)); |
1010 } | 1013 } |
1011 Bind(&uint16_elements); | 1014 Bind(&uint16_elements); |
1012 { | 1015 { |
1013 Comment("UINT16_ELEMENTS"); | 1016 Comment("UINT16_ELEMENTS"); |
1014 Node* index = WordShl(intptr_index, IntPtrConstant(1)); | 1017 Node* index = WordShl(intptr_index, IntPtrConstant(1)); |
1015 Node* element = Load(MachineType::Uint16(), backing_store, index); | 1018 Node* element = Load(MachineType::Uint16(), backing_store, index); |
1016 Return(SmiFromWord32(element)); | 1019 exit_point->Return(SmiFromWord32(element)); |
1017 } | 1020 } |
1018 Bind(&int16_elements); | 1021 Bind(&int16_elements); |
1019 { | 1022 { |
1020 Comment("INT16_ELEMENTS"); | 1023 Comment("INT16_ELEMENTS"); |
1021 Node* index = WordShl(intptr_index, IntPtrConstant(1)); | 1024 Node* index = WordShl(intptr_index, IntPtrConstant(1)); |
1022 Node* element = Load(MachineType::Int16(), backing_store, index); | 1025 Node* element = Load(MachineType::Int16(), backing_store, index); |
1023 Return(SmiFromWord32(element)); | 1026 exit_point->Return(SmiFromWord32(element)); |
1024 } | 1027 } |
1025 Bind(&uint32_elements); | 1028 Bind(&uint32_elements); |
1026 { | 1029 { |
1027 Comment("UINT32_ELEMENTS"); | 1030 Comment("UINT32_ELEMENTS"); |
1028 Node* index = WordShl(intptr_index, IntPtrConstant(2)); | 1031 Node* index = WordShl(intptr_index, IntPtrConstant(2)); |
1029 Node* element = Load(MachineType::Uint32(), backing_store, index); | 1032 Node* element = Load(MachineType::Uint32(), backing_store, index); |
1030 Return(ChangeUint32ToTagged(element)); | 1033 exit_point->Return(ChangeUint32ToTagged(element)); |
1031 } | 1034 } |
1032 Bind(&int32_elements); | 1035 Bind(&int32_elements); |
1033 { | 1036 { |
1034 Comment("INT32_ELEMENTS"); | 1037 Comment("INT32_ELEMENTS"); |
1035 Node* index = WordShl(intptr_index, IntPtrConstant(2)); | 1038 Node* index = WordShl(intptr_index, IntPtrConstant(2)); |
1036 Node* element = Load(MachineType::Int32(), backing_store, index); | 1039 Node* element = Load(MachineType::Int32(), backing_store, index); |
1037 Return(ChangeInt32ToTagged(element)); | 1040 exit_point->Return(ChangeInt32ToTagged(element)); |
1038 } | 1041 } |
1039 Bind(&float32_elements); | 1042 Bind(&float32_elements); |
1040 { | 1043 { |
1041 Comment("FLOAT32_ELEMENTS"); | 1044 Comment("FLOAT32_ELEMENTS"); |
1042 Node* index = WordShl(intptr_index, IntPtrConstant(2)); | 1045 Node* index = WordShl(intptr_index, IntPtrConstant(2)); |
1043 Node* element = Load(MachineType::Float32(), backing_store, index); | 1046 Node* element = Load(MachineType::Float32(), backing_store, index); |
1044 var_double_value->Bind(ChangeFloat32ToFloat64(element)); | 1047 var_double_value->Bind(ChangeFloat32ToFloat64(element)); |
1045 Goto(rebox_double); | 1048 Goto(rebox_double); |
1046 } | 1049 } |
1047 Bind(&float64_elements); | 1050 Bind(&float64_elements); |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1094 Label done(this); | 1097 Label done(this); |
1095 NameDictionaryLookup<NameDictionary>(properties, name, miss, &var_name_index, | 1098 NameDictionaryLookup<NameDictionary>(properties, name, miss, &var_name_index, |
1096 &done); | 1099 &done); |
1097 Bind(&done); | 1100 Bind(&done); |
1098 } | 1101 } |
1099 | 1102 |
1100 void AccessorAssembler::GenericElementLoad(Node* receiver, Node* receiver_map, | 1103 void AccessorAssembler::GenericElementLoad(Node* receiver, Node* receiver_map, |
1101 Node* instance_type, Node* index, | 1104 Node* instance_type, Node* index, |
1102 Label* slow) { | 1105 Label* slow) { |
1103 Comment("integer index"); | 1106 Comment("integer index"); |
| 1107 |
| 1108 ExitPoint direct_exit(this); |
| 1109 |
1104 Label if_element_hole(this), if_oob(this); | 1110 Label if_element_hole(this), if_oob(this); |
1105 // Receivers requiring non-standard element accesses (interceptors, access | 1111 // Receivers requiring non-standard element accesses (interceptors, access |
1106 // checks, strings and string wrappers, proxies) are handled in the runtime. | 1112 // checks, strings and string wrappers, proxies) are handled in the runtime. |
1107 GotoIf(Int32LessThanOrEqual(instance_type, | 1113 GotoIf(Int32LessThanOrEqual(instance_type, |
1108 Int32Constant(LAST_CUSTOM_ELEMENTS_RECEIVER)), | 1114 Int32Constant(LAST_CUSTOM_ELEMENTS_RECEIVER)), |
1109 slow); | 1115 slow); |
1110 Node* elements = LoadElements(receiver); | 1116 Node* elements = LoadElements(receiver); |
1111 Node* elements_kind = LoadMapElementsKind(receiver_map); | 1117 Node* elements_kind = LoadMapElementsKind(receiver_map); |
1112 Node* is_jsarray_condition = | 1118 Node* is_jsarray_condition = |
1113 Word32Equal(instance_type, Int32Constant(JS_ARRAY_TYPE)); | 1119 Word32Equal(instance_type, Int32Constant(JS_ARRAY_TYPE)); |
1114 Variable var_double_value(this, MachineRepresentation::kFloat64); | 1120 Variable var_double_value(this, MachineRepresentation::kFloat64); |
1115 Label rebox_double(this, &var_double_value); | 1121 Label rebox_double(this, &var_double_value); |
1116 | 1122 |
1117 // Unimplemented elements kinds fall back to a runtime call. | 1123 // Unimplemented elements kinds fall back to a runtime call. |
1118 Label* unimplemented_elements_kind = slow; | 1124 Label* unimplemented_elements_kind = slow; |
1119 IncrementCounter(isolate()->counters()->ic_keyed_load_generic_smi(), 1); | 1125 IncrementCounter(isolate()->counters()->ic_keyed_load_generic_smi(), 1); |
1120 EmitElementLoad(receiver, elements, elements_kind, index, | 1126 EmitElementLoad(receiver, elements, elements_kind, index, |
1121 is_jsarray_condition, &if_element_hole, &rebox_double, | 1127 is_jsarray_condition, &if_element_hole, &rebox_double, |
1122 &var_double_value, unimplemented_elements_kind, &if_oob, | 1128 &var_double_value, unimplemented_elements_kind, &if_oob, slow, |
1123 slow); | 1129 &direct_exit); |
1124 | 1130 |
1125 Bind(&rebox_double); | 1131 Bind(&rebox_double); |
1126 Return(AllocateHeapNumberWithValue(var_double_value.value())); | 1132 Return(AllocateHeapNumberWithValue(var_double_value.value())); |
1127 | 1133 |
1128 Bind(&if_oob); | 1134 Bind(&if_oob); |
1129 { | 1135 { |
1130 Comment("out of bounds"); | 1136 Comment("out of bounds"); |
1131 // Negative keys can't take the fast OOB path. | 1137 // Negative keys can't take the fast OOB path. |
1132 GotoIf(IntPtrLessThan(index, IntPtrConstant(0)), slow); | 1138 GotoIf(IntPtrLessThan(index, IntPtrConstant(0)), slow); |
1133 // Positive OOB indices are effectively the same as hole loads. | 1139 // Positive OOB indices are effectively the same as hole loads. |
(...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1452 } | 1458 } |
1453 } | 1459 } |
1454 | 1460 |
1455 void AccessorAssembler::LoadICProtoArray( | 1461 void AccessorAssembler::LoadICProtoArray( |
1456 const LoadICParameters* p, Node* handler, | 1462 const LoadICParameters* p, Node* handler, |
1457 bool throw_reference_error_if_nonexistent) { | 1463 bool throw_reference_error_if_nonexistent) { |
1458 Label miss(this); | 1464 Label miss(this); |
1459 CSA_ASSERT(this, Word32BinaryNot(TaggedIsSmi(handler))); | 1465 CSA_ASSERT(this, Word32BinaryNot(TaggedIsSmi(handler))); |
1460 CSA_ASSERT(this, IsFixedArrayMap(LoadMap(handler))); | 1466 CSA_ASSERT(this, IsFixedArrayMap(LoadMap(handler))); |
1461 | 1467 |
| 1468 ExitPoint direct_exit(this); |
| 1469 |
1462 Node* smi_handler = LoadObjectField(handler, LoadHandler::kSmiHandlerOffset); | 1470 Node* smi_handler = LoadObjectField(handler, LoadHandler::kSmiHandlerOffset); |
1463 Node* handler_flags = SmiUntag(smi_handler); | 1471 Node* handler_flags = SmiUntag(smi_handler); |
1464 | 1472 |
1465 Node* handler_length = LoadAndUntagFixedArrayBaseLength(handler); | 1473 Node* handler_length = LoadAndUntagFixedArrayBaseLength(handler); |
1466 | 1474 |
1467 Node* holder = | 1475 Node* holder = |
1468 EmitLoadICProtoArrayCheck(p, handler, handler_length, handler_flags, | 1476 EmitLoadICProtoArrayCheck(p, handler, handler_length, handler_flags, |
1469 &miss, throw_reference_error_if_nonexistent); | 1477 &miss, throw_reference_error_if_nonexistent); |
1470 | 1478 |
1471 HandleLoadICSmiHandlerCase(p, holder, smi_handler, &miss, kOnlyProperties); | 1479 HandleLoadICSmiHandlerCase(p, holder, smi_handler, &miss, &direct_exit, |
| 1480 kOnlyProperties); |
1472 | 1481 |
1473 Bind(&miss); | 1482 Bind(&miss); |
1474 { | 1483 { |
1475 TailCallRuntime(Runtime::kLoadIC_Miss, p->context, p->receiver, p->name, | 1484 TailCallRuntime(Runtime::kLoadIC_Miss, p->context, p->receiver, p->name, |
1476 p->slot, p->vector); | 1485 p->slot, p->vector); |
1477 } | 1486 } |
1478 } | 1487 } |
1479 | 1488 |
1480 void AccessorAssembler::LoadGlobalIC(const LoadICParameters* p, | 1489 void AccessorAssembler::LoadGlobalIC_TryPropertyCellCase( |
1481 TypeofMode typeof_mode) { | 1490 Node* vector, Node* slot, ExitPoint* exit_point, Label* try_handler, |
1482 Label try_handler(this), call_handler(this), miss(this); | 1491 Label* miss, ParameterMode slot_mode) { |
1483 Node* weak_cell = | 1492 Comment("LoadGlobalIC_TryPropertyCellCase"); |
1484 LoadFixedArrayElement(p->vector, p->slot, 0, SMI_PARAMETERS); | 1493 |
| 1494 Node* weak_cell = LoadFixedArrayElement(vector, slot, 0, slot_mode); |
1485 CSA_ASSERT(this, HasInstanceType(weak_cell, WEAK_CELL_TYPE)); | 1495 CSA_ASSERT(this, HasInstanceType(weak_cell, WEAK_CELL_TYPE)); |
1486 | 1496 |
1487 // Load value or try handler case if the {weak_cell} is cleared. | 1497 // Load value or try handler case if the {weak_cell} is cleared. |
1488 Node* property_cell = LoadWeakCellValue(weak_cell, &try_handler); | 1498 Node* property_cell = LoadWeakCellValue(weak_cell, try_handler); |
1489 CSA_ASSERT(this, HasInstanceType(property_cell, PROPERTY_CELL_TYPE)); | 1499 CSA_ASSERT(this, HasInstanceType(property_cell, PROPERTY_CELL_TYPE)); |
1490 | 1500 |
1491 Node* value = LoadObjectField(property_cell, PropertyCell::kValueOffset); | 1501 Node* value = LoadObjectField(property_cell, PropertyCell::kValueOffset); |
1492 GotoIf(WordEqual(value, TheHoleConstant()), &miss); | 1502 GotoIf(WordEqual(value, TheHoleConstant()), miss); |
1493 Return(value); | 1503 exit_point->Return(value); |
| 1504 } |
1494 | 1505 |
1495 Node* handler; | 1506 void AccessorAssembler::LoadGlobalIC_TryHandlerCase(const LoadICParameters* p, |
1496 Bind(&try_handler); | 1507 TypeofMode typeof_mode, |
1497 { | 1508 ExitPoint* exit_point, |
1498 handler = | 1509 Label* miss) { |
1499 LoadFixedArrayElement(p->vector, p->slot, kPointerSize, SMI_PARAMETERS); | 1510 Comment("LoadGlobalIC_TryHandlerCase"); |
1500 CSA_ASSERT(this, Word32BinaryNot(TaggedIsSmi(handler))); | |
1501 GotoIf(WordEqual(handler, LoadRoot(Heap::kuninitialized_symbolRootIndex)), | |
1502 &miss); | |
1503 GotoIf(IsCodeMap(LoadMap(handler)), &call_handler); | |
1504 | 1511 |
1505 bool throw_reference_error_if_nonexistent = | 1512 Label call_handler(this); |
1506 typeof_mode == NOT_INSIDE_TYPEOF; | 1513 |
1507 HandleLoadGlobalICHandlerCase(p, handler, &miss, | 1514 Node* handler = |
1508 throw_reference_error_if_nonexistent); | 1515 LoadFixedArrayElement(p->vector, p->slot, kPointerSize, SMI_PARAMETERS); |
1509 } | 1516 CSA_ASSERT(this, Word32BinaryNot(TaggedIsSmi(handler))); |
| 1517 GotoIf(WordEqual(handler, LoadRoot(Heap::kuninitialized_symbolRootIndex)), |
| 1518 miss); |
| 1519 GotoIf(IsCodeMap(LoadMap(handler)), &call_handler); |
| 1520 |
| 1521 bool throw_reference_error_if_nonexistent = typeof_mode == NOT_INSIDE_TYPEOF; |
| 1522 HandleLoadGlobalICHandlerCase(p, handler, miss, exit_point, |
| 1523 throw_reference_error_if_nonexistent); |
1510 | 1524 |
1511 Bind(&call_handler); | 1525 Bind(&call_handler); |
1512 { | 1526 { |
1513 LoadWithVectorDescriptor descriptor(isolate()); | 1527 LoadWithVectorDescriptor descriptor(isolate()); |
1514 Node* native_context = LoadNativeContext(p->context); | 1528 Node* native_context = LoadNativeContext(p->context); |
1515 Node* receiver = | 1529 Node* receiver = |
1516 LoadContextElement(native_context, Context::EXTENSION_INDEX); | 1530 LoadContextElement(native_context, Context::EXTENSION_INDEX); |
1517 TailCallStub(descriptor, handler, p->context, receiver, p->name, p->slot, | 1531 exit_point->ReturnCallStub(descriptor, handler, p->context, receiver, |
1518 p->vector); | 1532 p->name, p->slot, p->vector); |
1519 } | |
1520 Bind(&miss); | |
1521 { | |
1522 TailCallRuntime(Runtime::kLoadGlobalIC_Miss, p->context, p->name, p->slot, | |
1523 p->vector); | |
1524 } | 1533 } |
1525 } | 1534 } |
1526 | 1535 |
| 1536 void AccessorAssembler::LoadGlobalIC_MissCase(const LoadICParameters* p, |
| 1537 ExitPoint* exit_point) { |
| 1538 Comment("LoadGlobalIC_MissCase"); |
| 1539 |
| 1540 exit_point->ReturnCallRuntime(Runtime::kLoadGlobalIC_Miss, p->context, |
| 1541 p->name, p->slot, p->vector); |
| 1542 } |
| 1543 |
| 1544 void AccessorAssembler::LoadGlobalIC(const LoadICParameters* p, |
| 1545 TypeofMode typeof_mode) { |
| 1546 ExitPoint direct_exit(this); |
| 1547 |
| 1548 Label try_handler(this), miss(this); |
| 1549 LoadGlobalIC_TryPropertyCellCase(p->vector, p->slot, &direct_exit, |
| 1550 &try_handler, &miss); |
| 1551 |
| 1552 Bind(&try_handler); |
| 1553 LoadGlobalIC_TryHandlerCase(p, typeof_mode, &direct_exit, &miss); |
| 1554 |
| 1555 Bind(&miss); |
| 1556 LoadGlobalIC_MissCase(p, &direct_exit); |
| 1557 } |
| 1558 |
1527 void AccessorAssembler::KeyedLoadIC(const LoadICParameters* p) { | 1559 void AccessorAssembler::KeyedLoadIC(const LoadICParameters* p) { |
1528 Variable var_handler(this, MachineRepresentation::kTagged); | 1560 Variable var_handler(this, MachineRepresentation::kTagged); |
1529 // TODO(ishell): defer blocks when it works. | 1561 // TODO(ishell): defer blocks when it works. |
1530 Label if_handler(this, &var_handler), try_polymorphic(this), | 1562 Label if_handler(this, &var_handler), try_polymorphic(this), |
1531 try_megamorphic(this /*, Label::kDeferred*/), | 1563 try_megamorphic(this /*, Label::kDeferred*/), |
1532 try_polymorphic_name(this /*, Label::kDeferred*/), | 1564 try_polymorphic_name(this /*, Label::kDeferred*/), |
1533 miss(this /*, Label::kDeferred*/); | 1565 miss(this /*, Label::kDeferred*/); |
1534 | 1566 |
1535 Node* receiver_map = LoadReceiverMap(p->receiver); | 1567 Node* receiver_map = LoadReceiverMap(p->receiver); |
1536 | 1568 |
(...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1822 void AccessorAssembler::GenerateLoadField() { | 1854 void AccessorAssembler::GenerateLoadField() { |
1823 typedef LoadFieldDescriptor Descriptor; | 1855 typedef LoadFieldDescriptor Descriptor; |
1824 | 1856 |
1825 Node* receiver = Parameter(Descriptor::kReceiver); | 1857 Node* receiver = Parameter(Descriptor::kReceiver); |
1826 Node* name = nullptr; | 1858 Node* name = nullptr; |
1827 Node* slot = nullptr; | 1859 Node* slot = nullptr; |
1828 Node* vector = nullptr; | 1860 Node* vector = nullptr; |
1829 Node* context = Parameter(Descriptor::kContext); | 1861 Node* context = Parameter(Descriptor::kContext); |
1830 LoadICParameters p(context, receiver, name, slot, vector); | 1862 LoadICParameters p(context, receiver, name, slot, vector); |
1831 | 1863 |
| 1864 ExitPoint direct_exit(this); |
| 1865 |
1832 HandleLoadICSmiHandlerCase(&p, receiver, Parameter(Descriptor::kSmiHandler), | 1866 HandleLoadICSmiHandlerCase(&p, receiver, Parameter(Descriptor::kSmiHandler), |
1833 nullptr, kOnlyProperties); | 1867 nullptr, &direct_exit, kOnlyProperties); |
1834 } | 1868 } |
1835 | 1869 |
1836 void AccessorAssembler::GenerateLoadGlobalIC(TypeofMode typeof_mode) { | 1870 void AccessorAssembler::GenerateLoadGlobalIC(TypeofMode typeof_mode) { |
1837 typedef LoadGlobalWithVectorDescriptor Descriptor; | 1871 typedef LoadGlobalWithVectorDescriptor Descriptor; |
1838 | 1872 |
1839 Node* name = Parameter(Descriptor::kName); | 1873 Node* name = Parameter(Descriptor::kName); |
1840 Node* slot = Parameter(Descriptor::kSlot); | 1874 Node* slot = Parameter(Descriptor::kSlot); |
1841 Node* vector = Parameter(Descriptor::kVector); | 1875 Node* vector = Parameter(Descriptor::kVector); |
1842 Node* context = Parameter(Descriptor::kContext); | 1876 Node* context = Parameter(Descriptor::kContext); |
1843 | 1877 |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1948 Node* slot = Parameter(Descriptor::kSlot); | 1982 Node* slot = Parameter(Descriptor::kSlot); |
1949 Node* context = Parameter(Descriptor::kContext); | 1983 Node* context = Parameter(Descriptor::kContext); |
1950 Node* vector = LoadFeedbackVectorForStub(); | 1984 Node* vector = LoadFeedbackVectorForStub(); |
1951 | 1985 |
1952 StoreICParameters p(context, receiver, name, value, slot, vector); | 1986 StoreICParameters p(context, receiver, name, value, slot, vector); |
1953 KeyedStoreIC(&p, language_mode); | 1987 KeyedStoreIC(&p, language_mode); |
1954 } | 1988 } |
1955 | 1989 |
1956 } // namespace internal | 1990 } // namespace internal |
1957 } // namespace v8 | 1991 } // namespace v8 |
OLD | NEW |