OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 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/handler-compiler.h" | 5 #include "src/ic/handler-compiler.h" |
6 | 6 |
7 #include "src/field-type.h" | 7 #include "src/field-type.h" |
8 #include "src/ic/call-optimization.h" | 8 #include "src/ic/call-optimization.h" |
9 #include "src/ic/handler-configuration.h" | 9 #include "src/ic/handler-configuration.h" |
10 #include "src/ic/ic-inl.h" | 10 #include "src/ic/ic-inl.h" |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
122 Handle<Name> name, | 122 Handle<Name> name, |
123 Label* miss, | 123 Label* miss, |
124 ReturnHolder return_what) { | 124 ReturnHolder return_what) { |
125 return CheckPrototypes(object_reg, this->name(), scratch1(), scratch2(), name, | 125 return CheckPrototypes(object_reg, this->name(), scratch1(), scratch2(), name, |
126 miss, SKIP_RECEIVER, return_what); | 126 miss, SKIP_RECEIVER, return_what); |
127 } | 127 } |
128 | 128 |
129 | 129 |
130 Register PropertyHandlerCompiler::Frontend(Handle<Name> name) { | 130 Register PropertyHandlerCompiler::Frontend(Handle<Name> name) { |
131 Label miss; | 131 Label miss; |
132 if (IC::ICUseVector(kind())) { | 132 if (IC::ShouldPushPopSlotAndVector(kind())) { |
133 PushVectorAndSlot(); | 133 PushVectorAndSlot(); |
134 } | 134 } |
135 Register reg = FrontendHeader(receiver(), name, &miss, RETURN_HOLDER); | 135 Register reg = FrontendHeader(receiver(), name, &miss, RETURN_HOLDER); |
136 FrontendFooter(name, &miss); | 136 FrontendFooter(name, &miss); |
137 // The footer consumes the vector and slot from the stack if miss occurs. | 137 // The footer consumes the vector and slot from the stack if miss occurs. |
138 if (IC::ICUseVector(kind())) { | 138 if (IC::ShouldPushPopSlotAndVector(kind())) { |
139 DiscardVectorAndSlot(); | 139 DiscardVectorAndSlot(); |
140 } | 140 } |
141 return reg; | 141 return reg; |
142 } | 142 } |
143 | 143 |
144 | 144 |
145 void PropertyHandlerCompiler::NonexistentFrontendHeader(Handle<Name> name, | 145 void PropertyHandlerCompiler::NonexistentFrontendHeader(Handle<Name> name, |
146 Label* miss, | 146 Label* miss, |
147 Register scratch1, | 147 Register scratch1, |
148 Register scratch2) { | 148 Register scratch2) { |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
202 __ Move(receiver(), reg); | 202 __ Move(receiver(), reg); |
203 LoadConstantStub stub(isolate(), constant_index); | 203 LoadConstantStub stub(isolate(), constant_index); |
204 GenerateTailCall(masm(), stub.GetCode()); | 204 GenerateTailCall(masm(), stub.GetCode()); |
205 return GetCode(kind(), name); | 205 return GetCode(kind(), name); |
206 } | 206 } |
207 | 207 |
208 | 208 |
209 Handle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent( | 209 Handle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent( |
210 Handle<Name> name) { | 210 Handle<Name> name) { |
211 Label miss; | 211 Label miss; |
212 if (IC::ICUseVector(kind())) { | 212 if (IC::ShouldPushPopSlotAndVector(kind())) { |
213 DCHECK(kind() == Code::LOAD_IC); | 213 DCHECK(kind() == Code::LOAD_IC); |
214 PushVectorAndSlot(); | 214 PushVectorAndSlot(); |
215 } | 215 } |
216 NonexistentFrontendHeader(name, &miss, scratch2(), scratch3()); | 216 NonexistentFrontendHeader(name, &miss, scratch2(), scratch3()); |
217 if (IC::ICUseVector(kind())) { | 217 if (IC::ShouldPushPopSlotAndVector(kind())) { |
218 DiscardVectorAndSlot(); | 218 DiscardVectorAndSlot(); |
219 } | 219 } |
220 GenerateLoadConstant(isolate()->factory()->undefined_value()); | 220 GenerateLoadConstant(isolate()->factory()->undefined_value()); |
221 FrontendFooter(name, &miss); | 221 FrontendFooter(name, &miss); |
222 return GetCode(kind(), name); | 222 return GetCode(kind(), name); |
223 } | 223 } |
224 | 224 |
225 Handle<Code> NamedLoadHandlerCompiler::CompileLoadCallback( | 225 Handle<Code> NamedLoadHandlerCompiler::CompileLoadCallback( |
226 Handle<Name> name, Handle<AccessorInfo> callback, Handle<Code> slow_stub) { | 226 Handle<Name> name, Handle<AccessorInfo> callback, Handle<Code> slow_stub) { |
227 if (FLAG_runtime_call_stats) { | 227 if (FLAG_runtime_call_stats) { |
(...skipping 12 matching lines...) Expand all Loading... |
240 GenerateTailCall(masm(), slow_stub); | 240 GenerateTailCall(masm(), slow_stub); |
241 } | 241 } |
242 Register holder = Frontend(name); | 242 Register holder = Frontend(name); |
243 GenerateApiAccessorCall(masm(), call_optimization, map(), receiver(), | 243 GenerateApiAccessorCall(masm(), call_optimization, map(), receiver(), |
244 scratch2(), false, no_reg, holder, accessor_index); | 244 scratch2(), false, no_reg, holder, accessor_index); |
245 return GetCode(kind(), name); | 245 return GetCode(kind(), name); |
246 } | 246 } |
247 | 247 |
248 | 248 |
249 void NamedLoadHandlerCompiler::InterceptorVectorSlotPush(Register holder_reg) { | 249 void NamedLoadHandlerCompiler::InterceptorVectorSlotPush(Register holder_reg) { |
250 if (IC::ICUseVector(kind())) { | 250 if (IC::ShouldPushPopSlotAndVector(kind())) { |
251 if (holder_reg.is(receiver())) { | 251 if (holder_reg.is(receiver())) { |
252 PushVectorAndSlot(); | 252 PushVectorAndSlot(); |
253 } else { | 253 } else { |
254 DCHECK(holder_reg.is(scratch1())); | 254 DCHECK(holder_reg.is(scratch1())); |
255 PushVectorAndSlot(scratch2(), scratch3()); | 255 PushVectorAndSlot(scratch2(), scratch3()); |
256 } | 256 } |
257 } | 257 } |
258 } | 258 } |
259 | 259 |
260 | 260 |
261 void NamedLoadHandlerCompiler::InterceptorVectorSlotPop(Register holder_reg, | 261 void NamedLoadHandlerCompiler::InterceptorVectorSlotPop(Register holder_reg, |
262 PopMode mode) { | 262 PopMode mode) { |
263 if (IC::ICUseVector(kind())) { | 263 if (IC::ShouldPushPopSlotAndVector(kind())) { |
264 if (mode == DISCARD) { | 264 if (mode == DISCARD) { |
265 DiscardVectorAndSlot(); | 265 DiscardVectorAndSlot(); |
266 } else { | 266 } else { |
267 if (holder_reg.is(receiver())) { | 267 if (holder_reg.is(receiver())) { |
268 PopVectorAndSlot(); | 268 PopVectorAndSlot(); |
269 } else { | 269 } else { |
270 DCHECK(holder_reg.is(scratch1())); | 270 DCHECK(holder_reg.is(scratch1())); |
271 PopVectorAndSlot(scratch2(), scratch3()); | 271 PopVectorAndSlot(scratch2(), scratch3()); |
272 } | 272 } |
273 } | 273 } |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
431 expected_arguments, scratch2()); | 431 expected_arguments, scratch2()); |
432 return GetCode(kind(), name); | 432 return GetCode(kind(), name); |
433 } | 433 } |
434 | 434 |
435 | 435 |
436 // TODO(verwaest): Cleanup. holder() is actually the receiver. | 436 // TODO(verwaest): Cleanup. holder() is actually the receiver. |
437 Handle<Code> NamedStoreHandlerCompiler::CompileStoreTransition( | 437 Handle<Code> NamedStoreHandlerCompiler::CompileStoreTransition( |
438 Handle<Map> transition, Handle<Name> name) { | 438 Handle<Map> transition, Handle<Name> name) { |
439 Label miss; | 439 Label miss; |
440 | 440 |
441 bool vector_and_slot_on_stack = | 441 // Ensure that the StoreTransitionStub we are going to call has the same |
442 StoreTransitionDescriptor::PassVectorAndSlotOnStack(); | 442 // number of stack arguments. This means that we don't have to adapt them |
443 if (vector_and_slot_on_stack) { | 443 // if we decide to call the transition or miss stub. |
444 // Speculatively prepare for calling StoreTransitionStub by converting | 444 STATIC_ASSERT(StoreWithVectorDescriptor::kStackArgumentsCount == |
445 // StoreWithVectorDescriptor arguments to StoreTransitionDescriptor | 445 StoreTransitionDescriptor::kStackArgumentsCount); |
446 // arguments. | 446 STATIC_ASSERT(StoreWithVectorDescriptor::kStackArgumentsCount == 0 || |
447 PopReturnAddress(this->name()); | 447 StoreWithVectorDescriptor::kStackArgumentsCount == 3); |
448 PushVectorAndSlot(); | 448 STATIC_ASSERT(StoreWithVectorDescriptor::kParameterCount - |
449 PushReturnAddress(this->name()); | 449 StoreWithVectorDescriptor::kValue == |
450 } else { | 450 StoreTransitionDescriptor::kParameterCount - |
| 451 StoreTransitionDescriptor::kValue); |
| 452 STATIC_ASSERT(StoreWithVectorDescriptor::kParameterCount - |
| 453 StoreWithVectorDescriptor::kSlot == |
| 454 StoreTransitionDescriptor::kParameterCount - |
| 455 StoreTransitionDescriptor::kSlot); |
| 456 STATIC_ASSERT(StoreWithVectorDescriptor::kParameterCount - |
| 457 StoreWithVectorDescriptor::kVector == |
| 458 StoreTransitionDescriptor::kParameterCount - |
| 459 StoreTransitionDescriptor::kVector); |
| 460 |
| 461 bool need_save_restore = IC::ShouldPushPopSlotAndVector(kind()); |
| 462 if (need_save_restore) { |
451 PushVectorAndSlot(); | 463 PushVectorAndSlot(); |
452 } | 464 } |
453 | 465 |
454 // Check that we are allowed to write this. | 466 // Check that we are allowed to write this. |
455 bool is_nonexistent = holder()->map() == transition->GetBackPointer(); | 467 bool is_nonexistent = holder()->map() == transition->GetBackPointer(); |
456 if (is_nonexistent) { | 468 if (is_nonexistent) { |
457 // Find the top object. | 469 // Find the top object. |
458 Handle<JSObject> last; | 470 Handle<JSObject> last; |
459 PrototypeIterator::WhereToEnd end = | 471 PrototypeIterator::WhereToEnd end = |
460 name->IsPrivate() ? PrototypeIterator::END_AT_NON_HIDDEN | 472 name->IsPrivate() ? PrototypeIterator::END_AT_NON_HIDDEN |
(...skipping 19 matching lines...) Expand all Loading... |
480 // Stub is never generated for objects that require access checks. | 492 // Stub is never generated for objects that require access checks. |
481 DCHECK(!transition->is_access_check_needed()); | 493 DCHECK(!transition->is_access_check_needed()); |
482 | 494 |
483 // Call to respective StoreTransitionStub. | 495 // Call to respective StoreTransitionStub. |
484 Register map_reg = StoreTransitionDescriptor::MapRegister(); | 496 Register map_reg = StoreTransitionDescriptor::MapRegister(); |
485 | 497 |
486 if (details.type() == DATA_CONSTANT) { | 498 if (details.type() == DATA_CONSTANT) { |
487 DCHECK(descriptors->GetValue(descriptor)->IsJSFunction()); | 499 DCHECK(descriptors->GetValue(descriptor)->IsJSFunction()); |
488 GenerateRestoreMap(transition, map_reg, scratch1(), &miss); | 500 GenerateRestoreMap(transition, map_reg, scratch1(), &miss); |
489 GenerateConstantCheck(map_reg, descriptor, value(), scratch1(), &miss); | 501 GenerateConstantCheck(map_reg, descriptor, value(), scratch1(), &miss); |
490 if (!vector_and_slot_on_stack) { | 502 if (need_save_restore) { |
491 PopVectorAndSlot(); | 503 PopVectorAndSlot(); |
492 } | 504 } |
493 GenerateRestoreName(name); | 505 GenerateRestoreName(name); |
494 StoreTransitionStub stub(isolate()); | 506 StoreTransitionStub stub(isolate()); |
495 GenerateTailCall(masm(), stub.GetCode()); | 507 GenerateTailCall(masm(), stub.GetCode()); |
496 | 508 |
497 } else { | 509 } else { |
498 if (representation.IsHeapObject()) { | 510 if (representation.IsHeapObject()) { |
499 GenerateFieldTypeChecks(descriptors->GetFieldType(descriptor), value(), | 511 GenerateFieldTypeChecks(descriptors->GetFieldType(descriptor), value(), |
500 &miss); | 512 &miss); |
501 } | 513 } |
502 StoreTransitionStub::StoreMode store_mode = | 514 StoreTransitionStub::StoreMode store_mode = |
503 Map::cast(transition->GetBackPointer())->unused_property_fields() == 0 | 515 Map::cast(transition->GetBackPointer())->unused_property_fields() == 0 |
504 ? StoreTransitionStub::ExtendStorageAndStoreMapAndValue | 516 ? StoreTransitionStub::ExtendStorageAndStoreMapAndValue |
505 : StoreTransitionStub::StoreMapAndValue; | 517 : StoreTransitionStub::StoreMapAndValue; |
506 GenerateRestoreMap(transition, map_reg, scratch1(), &miss); | 518 GenerateRestoreMap(transition, map_reg, scratch1(), &miss); |
507 if (!vector_and_slot_on_stack) { | 519 if (need_save_restore) { |
508 PopVectorAndSlot(); | 520 PopVectorAndSlot(); |
509 } | 521 } |
510 GenerateRestoreName(name); | 522 GenerateRestoreName(name); |
511 StoreTransitionStub stub(isolate(), | 523 StoreTransitionStub stub(isolate(), |
512 FieldIndex::ForDescriptor(*transition, descriptor), | 524 FieldIndex::ForDescriptor(*transition, descriptor), |
513 representation, store_mode); | 525 representation, store_mode); |
514 GenerateTailCall(masm(), stub.GetCode()); | 526 GenerateTailCall(masm(), stub.GetCode()); |
515 } | 527 } |
516 | 528 |
517 __ bind(&miss); | 529 __ bind(&miss); |
518 if (vector_and_slot_on_stack) { | 530 if (need_save_restore) { |
519 // Prepare for calling miss builtin with StoreWithVectorDescriptor. | |
520 PopReturnAddress(this->name()); | |
521 PopVectorAndSlot(); | |
522 PushReturnAddress(this->name()); | |
523 } else { | |
524 PopVectorAndSlot(); | 531 PopVectorAndSlot(); |
525 } | 532 } |
526 GenerateRestoreName(name); | 533 GenerateRestoreName(name); |
527 TailCallBuiltin(masm(), MissBuiltin(kind())); | 534 TailCallBuiltin(masm(), MissBuiltin(kind())); |
528 | 535 |
529 return GetCode(kind(), name); | 536 return GetCode(kind(), name); |
530 } | 537 } |
531 | 538 |
532 bool NamedStoreHandlerCompiler::RequiresFieldTypeChecks( | 539 bool NamedStoreHandlerCompiler::RequiresFieldTypeChecks( |
533 FieldType* field_type) const { | 540 FieldType* field_type) const { |
534 return field_type->IsClass(); | 541 return field_type->IsClass(); |
535 } | 542 } |
536 | 543 |
537 | 544 |
538 Handle<Code> NamedStoreHandlerCompiler::CompileStoreField(LookupIterator* it) { | 545 Handle<Code> NamedStoreHandlerCompiler::CompileStoreField(LookupIterator* it) { |
539 Label miss; | 546 Label miss; |
540 DCHECK(it->representation().IsHeapObject()); | 547 DCHECK(it->representation().IsHeapObject()); |
541 | 548 |
542 FieldType* field_type = *it->GetFieldType(); | 549 FieldType* field_type = *it->GetFieldType(); |
543 bool need_save_restore = false; | 550 bool need_save_restore = false; |
544 if (RequiresFieldTypeChecks(field_type)) { | 551 if (RequiresFieldTypeChecks(field_type)) { |
545 need_save_restore = IC::ICUseVector(kind()); | 552 need_save_restore = IC::ShouldPushPopSlotAndVector(kind()); |
546 if (need_save_restore) PushVectorAndSlot(); | 553 if (need_save_restore) PushVectorAndSlot(); |
547 GenerateFieldTypeChecks(field_type, value(), &miss); | 554 GenerateFieldTypeChecks(field_type, value(), &miss); |
548 if (need_save_restore) PopVectorAndSlot(); | 555 if (need_save_restore) PopVectorAndSlot(); |
549 } | 556 } |
550 | 557 |
551 StoreFieldStub stub(isolate(), it->GetFieldIndex(), it->representation()); | 558 StoreFieldStub stub(isolate(), it->GetFieldIndex(), it->representation()); |
552 GenerateTailCall(masm(), stub.GetCode()); | 559 GenerateTailCall(masm(), stub.GetCode()); |
553 | 560 |
554 __ bind(&miss); | 561 __ bind(&miss); |
555 if (need_save_restore) PopVectorAndSlot(); | 562 if (need_save_restore) PopVectorAndSlot(); |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
642 } | 649 } |
643 | 650 |
644 void ElementHandlerCompiler::CompileElementHandlers( | 651 void ElementHandlerCompiler::CompileElementHandlers( |
645 MapHandleList* receiver_maps, List<Handle<Object>>* handlers) { | 652 MapHandleList* receiver_maps, List<Handle<Object>>* handlers) { |
646 for (int i = 0; i < receiver_maps->length(); ++i) { | 653 for (int i = 0; i < receiver_maps->length(); ++i) { |
647 handlers->Add(GetKeyedLoadHandler(receiver_maps->at(i), isolate())); | 654 handlers->Add(GetKeyedLoadHandler(receiver_maps->at(i), isolate())); |
648 } | 655 } |
649 } | 656 } |
650 } // namespace internal | 657 } // namespace internal |
651 } // namespace v8 | 658 } // namespace v8 |
OLD | NEW |