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 #if V8_TARGET_ARCH_IA32 | 5 #if V8_TARGET_ARCH_IA32 |
6 | 6 |
7 #include "src/ic/handler-compiler.h" | 7 #include "src/ic/handler-compiler.h" |
8 | 8 |
9 #include "src/api-arguments.h" | 9 #include "src/api-arguments.h" |
10 #include "src/field-type.h" | 10 #include "src/field-type.h" |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
158 // the version above. It is an optimization that should will be removed | 158 // the version above. It is an optimization that should will be removed |
159 // when api call ICs are generated in hydrogen. | 159 // when api call ICs are generated in hydrogen. |
160 void PropertyHandlerCompiler::GenerateApiAccessorCall( | 160 void PropertyHandlerCompiler::GenerateApiAccessorCall( |
161 MacroAssembler* masm, const CallOptimization& optimization, | 161 MacroAssembler* masm, const CallOptimization& optimization, |
162 Handle<Map> receiver_map, Register receiver, Register scratch, | 162 Handle<Map> receiver_map, Register receiver, Register scratch, |
163 bool is_store, Register store_parameter, Register accessor_holder, | 163 bool is_store, Register store_parameter, Register accessor_holder, |
164 int accessor_index) { | 164 int accessor_index) { |
165 DCHECK(!accessor_holder.is(scratch)); | 165 DCHECK(!accessor_holder.is(scratch)); |
166 // Copy return value. | 166 // Copy return value. |
167 __ pop(scratch); | 167 __ pop(scratch); |
| 168 |
| 169 if (is_store) { |
| 170 // Discard stack arguments. |
| 171 __ add(esp, Immediate(StoreWithVectorDescriptor::kStackArgumentsCount * |
| 172 kPointerSize)); |
| 173 } |
| 174 |
168 // receiver | 175 // receiver |
169 __ push(receiver); | 176 __ push(receiver); |
170 // Write the arguments to stack frame. | 177 // Write the arguments to stack frame. |
171 if (is_store) { | 178 if (is_store) { |
172 DCHECK(!receiver.is(store_parameter)); | 179 DCHECK(!receiver.is(store_parameter)); |
173 DCHECK(!scratch.is(store_parameter)); | 180 DCHECK(!scratch.is(store_parameter)); |
174 __ push(store_parameter); | 181 __ push(store_parameter); |
175 } | 182 } |
176 __ push(scratch); | 183 __ push(scratch); |
177 // Stack now matches JSFunction abi. | 184 // Stack now matches JSFunction abi. |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
298 // If we generate a global code snippet for deoptimization only, remember | 305 // If we generate a global code snippet for deoptimization only, remember |
299 // the place to continue after deoptimization. | 306 // the place to continue after deoptimization. |
300 masm->isolate()->heap()->SetSetterStubDeoptPCOffset(masm->pc_offset()); | 307 masm->isolate()->heap()->SetSetterStubDeoptPCOffset(masm->pc_offset()); |
301 } | 308 } |
302 | 309 |
303 // We have to return the passed value, not the return value of the setter. | 310 // We have to return the passed value, not the return value of the setter. |
304 __ pop(eax); | 311 __ pop(eax); |
305 // Restore context register. | 312 // Restore context register. |
306 __ pop(esi); | 313 __ pop(esi); |
307 } | 314 } |
308 __ ret(0); | 315 if (accessor_index >= 0) { |
| 316 __ ret(StoreWithVectorDescriptor::kStackArgumentsCount * kPointerSize); |
| 317 } else { |
| 318 // If we generate a global code snippet for deoptimization only, don't try |
| 319 // to drop stack arguments for the StoreIC because they are not a part of |
| 320 // expression stack and deoptimizer does not reconstruct them. |
| 321 __ ret(0); |
| 322 } |
309 } | 323 } |
310 | 324 |
311 | 325 |
312 static void PushInterceptorArguments(MacroAssembler* masm, Register receiver, | 326 static void PushInterceptorArguments(MacroAssembler* masm, Register receiver, |
313 Register holder, Register name, | 327 Register holder, Register name, |
314 Handle<JSObject> holder_obj) { | 328 Handle<JSObject> holder_obj) { |
315 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsNameIndex == 0); | 329 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsNameIndex == 0); |
316 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsThisIndex == 1); | 330 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsThisIndex == 1); |
317 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsHolderIndex == 2); | 331 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsHolderIndex == 2); |
318 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsLength == 3); | 332 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsLength == 3); |
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
501 // Return the register containing the holder. | 515 // Return the register containing the holder. |
502 return return_holder ? reg : no_reg; | 516 return return_holder ? reg : no_reg; |
503 } | 517 } |
504 | 518 |
505 | 519 |
506 void NamedLoadHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) { | 520 void NamedLoadHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) { |
507 if (!miss->is_unused()) { | 521 if (!miss->is_unused()) { |
508 Label success; | 522 Label success; |
509 __ jmp(&success); | 523 __ jmp(&success); |
510 __ bind(miss); | 524 __ bind(miss); |
511 if (IC::ICUseVector(kind())) { | 525 if (IC::ShouldPushPopSlotAndVector(kind())) { |
512 DCHECK(kind() == Code::LOAD_IC); | 526 DCHECK(kind() == Code::LOAD_IC); |
513 PopVectorAndSlot(); | 527 PopVectorAndSlot(); |
514 } | 528 } |
515 TailCallBuiltin(masm(), MissBuiltin(kind())); | 529 TailCallBuiltin(masm(), MissBuiltin(kind())); |
516 __ bind(&success); | 530 __ bind(&success); |
517 } | 531 } |
518 } | 532 } |
519 | 533 |
520 | 534 |
521 void NamedStoreHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) { | 535 void NamedStoreHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) { |
522 if (!miss->is_unused()) { | 536 if (!miss->is_unused()) { |
523 Label success; | 537 Label success; |
524 __ jmp(&success); | 538 __ jmp(&success); |
525 GenerateRestoreName(miss, name); | 539 GenerateRestoreName(miss, name); |
526 if (IC::ICUseVector(kind())) PopVectorAndSlot(); | 540 DCHECK(!IC::ShouldPushPopSlotAndVector(kind())); |
527 TailCallBuiltin(masm(), MissBuiltin(kind())); | 541 TailCallBuiltin(masm(), MissBuiltin(kind())); |
528 __ bind(&success); | 542 __ bind(&success); |
529 } | 543 } |
530 } | 544 } |
531 | 545 |
532 | 546 |
533 void NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) { | 547 void NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) { |
534 // Return the constant value. | 548 // Return the constant value. |
535 __ LoadObject(eax, value); | 549 __ LoadObject(eax, value); |
536 __ ret(0); | 550 __ ret(0); |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
617 __ TailCallRuntime(Runtime::kLoadPropertyWithInterceptor); | 631 __ TailCallRuntime(Runtime::kLoadPropertyWithInterceptor); |
618 } | 632 } |
619 | 633 |
620 | 634 |
621 Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( | 635 Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( |
622 Handle<JSObject> object, Handle<Name> name, Handle<AccessorInfo> callback, | 636 Handle<JSObject> object, Handle<Name> name, Handle<AccessorInfo> callback, |
623 LanguageMode language_mode) { | 637 LanguageMode language_mode) { |
624 Register holder_reg = Frontend(name); | 638 Register holder_reg = Frontend(name); |
625 | 639 |
626 __ pop(scratch1()); // remove the return address | 640 __ pop(scratch1()); // remove the return address |
| 641 // Discard stack arguments. |
| 642 __ add(esp, Immediate(StoreWithVectorDescriptor::kStackArgumentsCount * |
| 643 kPointerSize)); |
627 __ push(receiver()); | 644 __ push(receiver()); |
628 __ push(holder_reg); | 645 __ push(holder_reg); |
629 // If the callback cannot leak, then push the callback directly, | 646 // If the callback cannot leak, then push the callback directly, |
630 // otherwise wrap it in a weak cell. | 647 // otherwise wrap it in a weak cell. |
631 if (callback->data()->IsUndefined(isolate()) || callback->data()->IsSmi()) { | 648 if (callback->data()->IsUndefined(isolate()) || callback->data()->IsSmi()) { |
632 __ Push(callback); | 649 __ Push(callback); |
633 } else { | 650 } else { |
634 Handle<WeakCell> cell = isolate()->factory()->NewWeakCell(callback); | 651 Handle<WeakCell> cell = isolate()->factory()->NewWeakCell(callback); |
635 __ Push(cell); | 652 __ Push(cell); |
636 } | 653 } |
(...skipping 11 matching lines...) Expand all Loading... |
648 | 665 |
649 | 666 |
650 Register NamedStoreHandlerCompiler::value() { | 667 Register NamedStoreHandlerCompiler::value() { |
651 return StoreDescriptor::ValueRegister(); | 668 return StoreDescriptor::ValueRegister(); |
652 } | 669 } |
653 | 670 |
654 | 671 |
655 Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( | 672 Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( |
656 Handle<PropertyCell> cell, Handle<Name> name, bool is_configurable) { | 673 Handle<PropertyCell> cell, Handle<Name> name, bool is_configurable) { |
657 Label miss; | 674 Label miss; |
658 if (IC::ICUseVector(kind())) { | 675 if (IC::ShouldPushPopSlotAndVector(kind())) { |
659 PushVectorAndSlot(); | 676 PushVectorAndSlot(); |
660 } | 677 } |
661 FrontendHeader(receiver(), name, &miss, DONT_RETURN_ANYTHING); | 678 FrontendHeader(receiver(), name, &miss, DONT_RETURN_ANYTHING); |
662 // Get the value from the cell. | 679 // Get the value from the cell. |
663 Register result = StoreDescriptor::ValueRegister(); | 680 Register result = StoreDescriptor::ValueRegister(); |
664 Handle<WeakCell> weak_cell = factory()->NewWeakCell(cell); | 681 Handle<WeakCell> weak_cell = factory()->NewWeakCell(cell); |
665 __ LoadWeakValue(result, weak_cell, &miss); | 682 __ LoadWeakValue(result, weak_cell, &miss); |
666 __ mov(result, FieldOperand(result, PropertyCell::kValueOffset)); | 683 __ mov(result, FieldOperand(result, PropertyCell::kValueOffset)); |
667 | 684 |
668 // Check for deleted property if property can actually be deleted. | 685 // Check for deleted property if property can actually be deleted. |
669 if (is_configurable) { | 686 if (is_configurable) { |
670 __ cmp(result, factory()->the_hole_value()); | 687 __ cmp(result, factory()->the_hole_value()); |
671 __ j(equal, &miss); | 688 __ j(equal, &miss); |
672 } else if (FLAG_debug_code) { | 689 } else if (FLAG_debug_code) { |
673 __ cmp(result, factory()->the_hole_value()); | 690 __ cmp(result, factory()->the_hole_value()); |
674 __ Check(not_equal, kDontDeleteCellsCannotContainTheHole); | 691 __ Check(not_equal, kDontDeleteCellsCannotContainTheHole); |
675 } | 692 } |
676 | 693 |
677 Counters* counters = isolate()->counters(); | 694 Counters* counters = isolate()->counters(); |
678 __ IncrementCounter(counters->ic_named_load_global_stub(), 1); | 695 __ IncrementCounter(counters->ic_named_load_global_stub(), 1); |
679 // The code above already loads the result into the return register. | 696 // The code above already loads the result into the return register. |
680 if (IC::ICUseVector(kind())) { | 697 if (IC::ShouldPushPopSlotAndVector(kind())) { |
681 DiscardVectorAndSlot(); | 698 DiscardVectorAndSlot(); |
682 } | 699 } |
683 __ ret(0); | 700 __ ret(0); |
684 | 701 |
685 FrontendFooter(name, &miss); | 702 FrontendFooter(name, &miss); |
686 | 703 |
687 // Return the generated code. | 704 // Return the generated code. |
688 return GetCode(kind(), name); | 705 return GetCode(kind(), name); |
689 } | 706 } |
690 | 707 |
691 | 708 |
692 #undef __ | 709 #undef __ |
693 } // namespace internal | 710 } // namespace internal |
694 } // namespace v8 | 711 } // namespace v8 |
695 | 712 |
696 #endif // V8_TARGET_ARCH_IA32 | 713 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |