OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #if V8_TARGET_ARCH_X64 | 7 #if V8_TARGET_ARCH_X64 |
8 | 8 |
9 #include "src/arguments.h" | 9 #include "src/arguments.h" |
10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
(...skipping 356 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
367 } else if (!holder->HasFastProperties() && !holder->IsJSGlobalProxy()) { | 367 } else if (!holder->HasFastProperties() && !holder->IsJSGlobalProxy()) { |
368 GenerateDictionaryNegativeLookup( | 368 GenerateDictionaryNegativeLookup( |
369 masm, miss, holder_reg, name, scratch1(), scratch2()); | 369 masm, miss, holder_reg, name, scratch1(), scratch2()); |
370 } | 370 } |
371 } | 371 } |
372 | 372 |
373 | 373 |
374 // Receiver_reg is preserved on jumps to miss_label, but may be destroyed if | 374 // Receiver_reg is preserved on jumps to miss_label, but may be destroyed if |
375 // store is successful. | 375 // store is successful. |
376 void NamedStoreHandlerCompiler::GenerateStoreTransition( | 376 void NamedStoreHandlerCompiler::GenerateStoreTransition( |
377 MacroAssembler* masm, Handle<JSObject> object, LookupResult* lookup, | 377 MacroAssembler* masm, LookupResult* lookup, Handle<Map> transition, |
378 Handle<Map> transition, Handle<Name> name, Register receiver_reg, | 378 Handle<Name> name, Register receiver_reg, Register storage_reg, |
379 Register storage_reg, Register value_reg, Register scratch1, | 379 Register value_reg, Register scratch1, Register scratch2, Register unused, |
380 Register scratch2, Register unused, Label* miss_label, Label* slow) { | 380 Label* miss_label, Label* slow) { |
381 int descriptor = transition->LastAdded(); | 381 int descriptor = transition->LastAdded(); |
382 DescriptorArray* descriptors = transition->instance_descriptors(); | 382 DescriptorArray* descriptors = transition->instance_descriptors(); |
383 PropertyDetails details = descriptors->GetDetails(descriptor); | 383 PropertyDetails details = descriptors->GetDetails(descriptor); |
384 Representation representation = details.representation(); | 384 Representation representation = details.representation(); |
385 ASSERT(!representation.IsNone()); | 385 ASSERT(!representation.IsNone()); |
386 | 386 |
387 if (details.type() == CONSTANT) { | 387 if (details.type() == CONSTANT) { |
388 Handle<Object> constant(descriptors->GetValue(descriptor), masm->isolate()); | 388 Handle<Object> constant(descriptors->GetValue(descriptor), masm->isolate()); |
389 __ Cmp(value_reg, constant); | 389 __ Cmp(value_reg, constant); |
390 __ j(not_equal, miss_label); | 390 __ j(not_equal, miss_label); |
(...skipping 27 matching lines...) Expand all Loading... |
418 | 418 |
419 __ bind(&heap_number); | 419 __ bind(&heap_number); |
420 __ CheckMap(value_reg, masm->isolate()->factory()->heap_number_map(), | 420 __ CheckMap(value_reg, masm->isolate()->factory()->heap_number_map(), |
421 miss_label, DONT_DO_SMI_CHECK); | 421 miss_label, DONT_DO_SMI_CHECK); |
422 __ movsd(xmm0, FieldOperand(value_reg, HeapNumber::kValueOffset)); | 422 __ movsd(xmm0, FieldOperand(value_reg, HeapNumber::kValueOffset)); |
423 | 423 |
424 __ bind(&do_store); | 424 __ bind(&do_store); |
425 __ movsd(FieldOperand(storage_reg, HeapNumber::kValueOffset), xmm0); | 425 __ movsd(FieldOperand(storage_reg, HeapNumber::kValueOffset), xmm0); |
426 } | 426 } |
427 | 427 |
428 // Stub never generated for non-global objects that require access | 428 // Stub never generated for objects that require access checks. |
429 // checks. | 429 ASSERT(!transition->is_access_check_needed()); |
430 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); | |
431 | 430 |
432 // Perform map transition for the receiver if necessary. | 431 // Perform map transition for the receiver if necessary. |
433 if (details.type() == FIELD && | 432 if (details.type() == FIELD && |
434 object->map()->unused_property_fields() == 0) { | 433 Map::cast(transition->GetBackPointer())->unused_property_fields() == 0) { |
435 // The properties must be extended before we can store the value. | 434 // The properties must be extended before we can store the value. |
436 // We jump to a runtime call that extends the properties array. | 435 // We jump to a runtime call that extends the properties array. |
437 __ PopReturnAddressTo(scratch1); | 436 __ PopReturnAddressTo(scratch1); |
438 __ Push(receiver_reg); | 437 __ Push(receiver_reg); |
439 __ Push(transition); | 438 __ Push(transition); |
440 __ Push(value_reg); | 439 __ Push(value_reg); |
441 __ PushReturnAddressFrom(scratch1); | 440 __ PushReturnAddressFrom(scratch1); |
442 __ TailCallExternalReference( | 441 __ TailCallExternalReference( |
443 ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage), | 442 ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage), |
444 masm->isolate()), | 443 masm->isolate()), |
(...skipping 20 matching lines...) Expand all Loading... |
465 __ ret(0); | 464 __ ret(0); |
466 return; | 465 return; |
467 } | 466 } |
468 | 467 |
469 int index = transition->instance_descriptors()->GetFieldIndex( | 468 int index = transition->instance_descriptors()->GetFieldIndex( |
470 transition->LastAdded()); | 469 transition->LastAdded()); |
471 | 470 |
472 // Adjust for the number of properties stored in the object. Even in the | 471 // Adjust for the number of properties stored in the object. Even in the |
473 // face of a transition we can use the old map here because the size of the | 472 // face of a transition we can use the old map here because the size of the |
474 // object and the number of in-object properties is not going to change. | 473 // object and the number of in-object properties is not going to change. |
475 index -= object->map()->inobject_properties(); | 474 index -= transition->inobject_properties(); |
476 | 475 |
477 // TODO(verwaest): Share this code as a code stub. | 476 // TODO(verwaest): Share this code as a code stub. |
478 SmiCheck smi_check = representation.IsTagged() | 477 SmiCheck smi_check = representation.IsTagged() |
479 ? INLINE_SMI_CHECK : OMIT_SMI_CHECK; | 478 ? INLINE_SMI_CHECK : OMIT_SMI_CHECK; |
480 if (index < 0) { | 479 if (index < 0) { |
481 // Set the property straight into the object. | 480 // Set the property straight into the object. |
482 int offset = object->map()->instance_size() + (index * kPointerSize); | 481 int offset = transition->instance_size() + (index * kPointerSize); |
483 if (representation.IsDouble()) { | 482 if (representation.IsDouble()) { |
484 __ movp(FieldOperand(receiver_reg, offset), storage_reg); | 483 __ movp(FieldOperand(receiver_reg, offset), storage_reg); |
485 } else { | 484 } else { |
486 __ movp(FieldOperand(receiver_reg, offset), value_reg); | 485 __ movp(FieldOperand(receiver_reg, offset), value_reg); |
487 } | 486 } |
488 | 487 |
489 if (!representation.IsSmi()) { | 488 if (!representation.IsSmi()) { |
490 // Update the write barrier for the array address. | 489 // Update the write barrier for the array address. |
491 if (!representation.IsDouble()) { | 490 if (!representation.IsDouble()) { |
492 __ movp(storage_reg, value_reg); | 491 __ movp(storage_reg, value_reg); |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
626 Handle<Code> code) { | 625 Handle<Code> code) { |
627 __ jmp(code, RelocInfo::CODE_TARGET); | 626 __ jmp(code, RelocInfo::CODE_TARGET); |
628 } | 627 } |
629 | 628 |
630 | 629 |
631 #undef __ | 630 #undef __ |
632 #define __ ACCESS_MASM((masm())) | 631 #define __ ACCESS_MASM((masm())) |
633 | 632 |
634 | 633 |
635 Register PropertyHandlerCompiler::CheckPrototypes( | 634 Register PropertyHandlerCompiler::CheckPrototypes( |
636 Register object_reg, Handle<JSObject> holder, Register holder_reg, | 635 Register object_reg, Register holder_reg, Register scratch1, |
637 Register scratch1, Register scratch2, Handle<Name> name, Label* miss, | 636 Register scratch2, Handle<Name> name, Label* miss, |
638 PrototypeCheckType check) { | 637 PrototypeCheckType check) { |
639 Handle<Map> receiver_map(IC::TypeToMap(*type(), isolate())); | 638 Handle<Map> receiver_map(IC::TypeToMap(*type(), isolate())); |
640 | 639 |
641 // Make sure there's no overlap between holder and object registers. | 640 // Make sure there's no overlap between holder and object registers. |
642 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); | 641 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); |
643 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) | 642 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) |
644 && !scratch2.is(scratch1)); | 643 && !scratch2.is(scratch1)); |
645 | 644 |
646 // Keep track of the current object in register reg. On the first | 645 // Keep track of the current object in register reg. On the first |
647 // iteration, reg is an alias for object_reg, on later iterations, | 646 // iteration, reg is an alias for object_reg, on later iterations, |
648 // it is an alias for holder_reg. | 647 // it is an alias for holder_reg. |
649 Register reg = object_reg; | 648 Register reg = object_reg; |
650 int depth = 0; | 649 int depth = 0; |
651 | 650 |
652 Handle<JSObject> current = Handle<JSObject>::null(); | 651 Handle<JSObject> current = Handle<JSObject>::null(); |
653 if (type()->IsConstant()) { | 652 if (type()->IsConstant()) { |
654 current = Handle<JSObject>::cast(type()->AsConstant()->Value()); | 653 current = Handle<JSObject>::cast(type()->AsConstant()->Value()); |
655 } | 654 } |
656 Handle<JSObject> prototype = Handle<JSObject>::null(); | 655 Handle<JSObject> prototype = Handle<JSObject>::null(); |
657 Handle<Map> current_map = receiver_map; | 656 Handle<Map> current_map = receiver_map; |
658 Handle<Map> holder_map(holder->map()); | 657 Handle<Map> holder_map(holder()->map()); |
659 // Traverse the prototype chain and check the maps in the prototype chain for | 658 // Traverse the prototype chain and check the maps in the prototype chain for |
660 // fast and global objects or do negative lookup for normal objects. | 659 // fast and global objects or do negative lookup for normal objects. |
661 while (!current_map.is_identical_to(holder_map)) { | 660 while (!current_map.is_identical_to(holder_map)) { |
662 ++depth; | 661 ++depth; |
663 | 662 |
664 // Only global objects and objects that do not require access | 663 // Only global objects and objects that do not require access |
665 // checks are allowed in stubs. | 664 // checks are allowed in stubs. |
666 ASSERT(current_map->IsJSGlobalProxyMap() || | 665 ASSERT(current_map->IsJSGlobalProxyMap() || |
667 !current_map->is_access_check_needed()); | 666 !current_map->is_access_check_needed()); |
668 | 667 |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
759 Label success; | 758 Label success; |
760 __ jmp(&success); | 759 __ jmp(&success); |
761 GenerateRestoreName(masm(), miss, name); | 760 GenerateRestoreName(masm(), miss, name); |
762 TailCallBuiltin(masm(), MissBuiltin(kind())); | 761 TailCallBuiltin(masm(), MissBuiltin(kind())); |
763 __ bind(&success); | 762 __ bind(&success); |
764 } | 763 } |
765 } | 764 } |
766 | 765 |
767 | 766 |
768 Register NamedLoadHandlerCompiler::CallbackFrontend(Register object_reg, | 767 Register NamedLoadHandlerCompiler::CallbackFrontend(Register object_reg, |
769 Handle<JSObject> holder, | |
770 Handle<Name> name, | 768 Handle<Name> name, |
771 Handle<Object> callback) { | 769 Handle<Object> callback) { |
772 Label miss; | 770 Label miss; |
773 | 771 |
774 Register reg = FrontendHeader(object_reg, holder, name, &miss); | 772 Register reg = FrontendHeader(object_reg, name, &miss); |
775 | 773 |
776 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { | 774 if (!holder()->HasFastProperties()) { |
| 775 ASSERT(!holder()->IsGlobalObject()); |
777 ASSERT(!reg.is(scratch2())); | 776 ASSERT(!reg.is(scratch2())); |
778 ASSERT(!reg.is(scratch3())); | 777 ASSERT(!reg.is(scratch3())); |
779 ASSERT(!reg.is(scratch4())); | 778 ASSERT(!reg.is(scratch4())); |
780 | 779 |
781 // Load the properties dictionary. | 780 // Load the properties dictionary. |
782 Register dictionary = scratch4(); | 781 Register dictionary = scratch4(); |
783 __ movp(dictionary, FieldOperand(reg, JSObject::kPropertiesOffset)); | 782 __ movp(dictionary, FieldOperand(reg, JSObject::kPropertiesOffset)); |
784 | 783 |
785 // Probe the dictionary. | 784 // Probe the dictionary. |
786 Label probe_done; | 785 Label probe_done; |
(...skipping 20 matching lines...) Expand all Loading... |
807 __ cmpp(scratch2(), scratch3()); | 806 __ cmpp(scratch2(), scratch3()); |
808 __ j(not_equal, &miss); | 807 __ j(not_equal, &miss); |
809 } | 808 } |
810 | 809 |
811 FrontendFooter(name, &miss); | 810 FrontendFooter(name, &miss); |
812 return reg; | 811 return reg; |
813 } | 812 } |
814 | 813 |
815 | 814 |
816 void NamedLoadHandlerCompiler::GenerateLoadField( | 815 void NamedLoadHandlerCompiler::GenerateLoadField( |
817 Register reg, Handle<JSObject> holder, FieldIndex field, | 816 Register reg, FieldIndex field, Representation representation) { |
818 Representation representation) { | |
819 if (!reg.is(receiver())) __ movp(receiver(), reg); | 817 if (!reg.is(receiver())) __ movp(receiver(), reg); |
820 LoadFieldStub stub(isolate(), field); | 818 LoadFieldStub stub(isolate(), field); |
821 GenerateTailCall(masm(), stub.GetCode()); | 819 GenerateTailCall(masm(), stub.GetCode()); |
822 } | 820 } |
823 | 821 |
824 | 822 |
825 void NamedLoadHandlerCompiler::GenerateLoadCallback( | 823 void NamedLoadHandlerCompiler::GenerateLoadCallback( |
826 Register reg, Handle<ExecutableAccessorInfo> callback) { | 824 Register reg, Handle<ExecutableAccessorInfo> callback) { |
827 // Insert additional parameters into the stack frame above return address. | 825 // Insert additional parameters into the stack frame above return address. |
828 ASSERT(!scratch4().is(reg)); | 826 ASSERT(!scratch4().is(reg)); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
866 } | 864 } |
867 | 865 |
868 | 866 |
869 void NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) { | 867 void NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) { |
870 // Return the constant value. | 868 // Return the constant value. |
871 __ Move(rax, value); | 869 __ Move(rax, value); |
872 __ ret(0); | 870 __ ret(0); |
873 } | 871 } |
874 | 872 |
875 | 873 |
876 void NamedLoadHandlerCompiler::GenerateLoadInterceptor( | 874 void NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg, |
877 Register holder_reg, Handle<JSObject> interceptor_holder, | 875 LookupResult* lookup, |
878 LookupResult* lookup, Handle<Name> name) { | 876 Handle<Name> name) { |
879 ASSERT(interceptor_holder->HasNamedInterceptor()); | 877 ASSERT(holder()->HasNamedInterceptor()); |
880 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); | 878 ASSERT(!holder()->GetNamedInterceptor()->getter()->IsUndefined()); |
881 | 879 |
882 // So far the most popular follow ups for interceptor loads are FIELD | 880 // So far the most popular follow ups for interceptor loads are FIELD |
883 // and CALLBACKS, so inline only them, other cases may be added | 881 // and CALLBACKS, so inline only them, other cases may be added |
884 // later. | 882 // later. |
885 bool compile_followup_inline = false; | 883 bool compile_followup_inline = false; |
886 if (lookup->IsFound() && lookup->IsCacheable()) { | 884 if (lookup->IsFound() && lookup->IsCacheable()) { |
887 if (lookup->IsField()) { | 885 if (lookup->IsField()) { |
888 compile_followup_inline = true; | 886 compile_followup_inline = true; |
889 } else if (lookup->type() == CALLBACKS && | 887 } else if (lookup->type() == CALLBACKS && |
890 lookup->GetCallbackObject()->IsExecutableAccessorInfo()) { | 888 lookup->GetCallbackObject()->IsExecutableAccessorInfo()) { |
891 Handle<ExecutableAccessorInfo> callback( | 889 Handle<ExecutableAccessorInfo> callback( |
892 ExecutableAccessorInfo::cast(lookup->GetCallbackObject())); | 890 ExecutableAccessorInfo::cast(lookup->GetCallbackObject())); |
893 compile_followup_inline = | 891 compile_followup_inline = |
894 callback->getter() != NULL && | 892 callback->getter() != NULL && |
895 ExecutableAccessorInfo::IsCompatibleReceiverType(isolate(), callback, | 893 ExecutableAccessorInfo::IsCompatibleReceiverType(isolate(), callback, |
896 type()); | 894 type()); |
897 } | 895 } |
898 } | 896 } |
899 | 897 |
900 if (compile_followup_inline) { | 898 if (compile_followup_inline) { |
901 // Compile the interceptor call, followed by inline code to load the | 899 // Compile the interceptor call, followed by inline code to load the |
902 // property from further up the prototype chain if the call fails. | 900 // property from further up the prototype chain if the call fails. |
903 // Check that the maps haven't changed. | 901 // Check that the maps haven't changed. |
904 ASSERT(holder_reg.is(receiver()) || holder_reg.is(scratch1())); | 902 ASSERT(holder_reg.is(receiver()) || holder_reg.is(scratch1())); |
905 | 903 |
906 // Preserve the receiver register explicitly whenever it is different from | 904 // Preserve the receiver register explicitly whenever it is different from |
907 // the holder and it is needed should the interceptor return without any | 905 // the holder and it is needed should the interceptor return without any |
908 // result. The CALLBACKS case needs the receiver to be passed into C++ code, | 906 // result. The CALLBACKS case needs the receiver to be passed into C++ code, |
909 // the FIELD case might cause a miss during the prototype check. | 907 // the FIELD case might cause a miss during the prototype check. |
910 bool must_perfrom_prototype_check = *interceptor_holder != lookup->holder(); | 908 bool must_perfrom_prototype_check = *holder() != lookup->holder(); |
911 bool must_preserve_receiver_reg = !receiver().is(holder_reg) && | 909 bool must_preserve_receiver_reg = !receiver().is(holder_reg) && |
912 (lookup->type() == CALLBACKS || must_perfrom_prototype_check); | 910 (lookup->type() == CALLBACKS || must_perfrom_prototype_check); |
913 | 911 |
914 // Save necessary data before invoking an interceptor. | 912 // Save necessary data before invoking an interceptor. |
915 // Requires a frame to make GC aware of pushed pointers. | 913 // Requires a frame to make GC aware of pushed pointers. |
916 { | 914 { |
917 FrameScope frame_scope(masm(), StackFrame::INTERNAL); | 915 FrameScope frame_scope(masm(), StackFrame::INTERNAL); |
918 | 916 |
919 if (must_preserve_receiver_reg) { | 917 if (must_preserve_receiver_reg) { |
920 __ Push(receiver()); | 918 __ Push(receiver()); |
921 } | 919 } |
922 __ Push(holder_reg); | 920 __ Push(holder_reg); |
923 __ Push(this->name()); | 921 __ Push(this->name()); |
924 | 922 |
925 // Invoke an interceptor. Note: map checks from receiver to | 923 // Invoke an interceptor. Note: map checks from receiver to |
926 // interceptor's holder has been compiled before (see a caller | 924 // interceptor's holder has been compiled before (see a caller |
927 // of this method.) | 925 // of this method.) |
928 CompileCallLoadPropertyWithInterceptor( | 926 CompileCallLoadPropertyWithInterceptor( |
929 masm(), receiver(), holder_reg, this->name(), interceptor_holder, | 927 masm(), receiver(), holder_reg, this->name(), holder(), |
930 IC::kLoadPropertyWithInterceptorOnly); | 928 IC::kLoadPropertyWithInterceptorOnly); |
931 | 929 |
932 // Check if interceptor provided a value for property. If it's | 930 // Check if interceptor provided a value for property. If it's |
933 // the case, return immediately. | 931 // the case, return immediately. |
934 Label interceptor_failed; | 932 Label interceptor_failed; |
935 __ CompareRoot(rax, Heap::kNoInterceptorResultSentinelRootIndex); | 933 __ CompareRoot(rax, Heap::kNoInterceptorResultSentinelRootIndex); |
936 __ j(equal, &interceptor_failed); | 934 __ j(equal, &interceptor_failed); |
937 frame_scope.GenerateLeaveFrame(); | 935 frame_scope.GenerateLeaveFrame(); |
938 __ ret(0); | 936 __ ret(0); |
939 | 937 |
940 __ bind(&interceptor_failed); | 938 __ bind(&interceptor_failed); |
941 __ Pop(this->name()); | 939 __ Pop(this->name()); |
942 __ Pop(holder_reg); | 940 __ Pop(holder_reg); |
943 if (must_preserve_receiver_reg) { | 941 if (must_preserve_receiver_reg) { |
944 __ Pop(receiver()); | 942 __ Pop(receiver()); |
945 } | 943 } |
946 | 944 |
947 // Leave the internal frame. | 945 // Leave the internal frame. |
948 } | 946 } |
949 | 947 |
950 GenerateLoadPostInterceptor(holder_reg, interceptor_holder, name, lookup); | 948 GenerateLoadPostInterceptor(holder_reg, name, lookup); |
951 } else { // !compile_followup_inline | 949 } else { // !compile_followup_inline |
952 // Call the runtime system to load the interceptor. | 950 // Call the runtime system to load the interceptor. |
953 // Check that the maps haven't changed. | 951 // Check that the maps haven't changed. |
954 __ PopReturnAddressTo(scratch2()); | 952 __ PopReturnAddressTo(scratch2()); |
955 PushInterceptorArguments(masm(), receiver(), holder_reg, | 953 PushInterceptorArguments(masm(), receiver(), holder_reg, this->name(), |
956 this->name(), interceptor_holder); | 954 holder()); |
957 __ PushReturnAddressFrom(scratch2()); | 955 __ PushReturnAddressFrom(scratch2()); |
958 | 956 |
959 ExternalReference ref = ExternalReference( | 957 ExternalReference ref = ExternalReference( |
960 IC_Utility(IC::kLoadPropertyWithInterceptor), isolate()); | 958 IC_Utility(IC::kLoadPropertyWithInterceptor), isolate()); |
961 __ TailCallExternalReference( | 959 __ TailCallExternalReference( |
962 ref, NamedLoadHandlerCompiler::kInterceptorArgsLength, 1); | 960 ref, NamedLoadHandlerCompiler::kInterceptorArgsLength, 1); |
963 } | 961 } |
964 } | 962 } |
965 | 963 |
966 | 964 |
967 Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( | 965 Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( |
968 Handle<JSObject> object, Handle<JSObject> holder, Handle<Name> name, | 966 Handle<JSObject> object, Handle<Name> name, |
969 Handle<ExecutableAccessorInfo> callback) { | 967 Handle<ExecutableAccessorInfo> callback) { |
970 Register holder_reg = Frontend(receiver(), holder, name); | 968 Register holder_reg = Frontend(receiver(), name); |
971 | 969 |
972 __ PopReturnAddressTo(scratch1()); | 970 __ PopReturnAddressTo(scratch1()); |
973 __ Push(receiver()); | 971 __ Push(receiver()); |
974 __ Push(holder_reg); | 972 __ Push(holder_reg); |
975 __ Push(callback); // callback info | 973 __ Push(callback); // callback info |
976 __ Push(name); | 974 __ Push(name); |
977 __ Push(value()); | 975 __ Push(value()); |
978 __ PushReturnAddressFrom(scratch1()); | 976 __ PushReturnAddressFrom(scratch1()); |
979 | 977 |
980 // Do tail-call to the runtime system. | 978 // Do tail-call to the runtime system. |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1030 } | 1028 } |
1031 __ ret(0); | 1029 __ ret(0); |
1032 } | 1030 } |
1033 | 1031 |
1034 | 1032 |
1035 #undef __ | 1033 #undef __ |
1036 #define __ ACCESS_MASM(masm()) | 1034 #define __ ACCESS_MASM(masm()) |
1037 | 1035 |
1038 | 1036 |
1039 Handle<Code> NamedStoreHandlerCompiler::CompileStoreInterceptor( | 1037 Handle<Code> NamedStoreHandlerCompiler::CompileStoreInterceptor( |
1040 Handle<JSObject> object, Handle<Name> name) { | 1038 Handle<Name> name) { |
1041 __ PopReturnAddressTo(scratch1()); | 1039 __ PopReturnAddressTo(scratch1()); |
1042 __ Push(receiver()); | 1040 __ Push(receiver()); |
1043 __ Push(this->name()); | 1041 __ Push(this->name()); |
1044 __ Push(value()); | 1042 __ Push(value()); |
1045 __ PushReturnAddressFrom(scratch1()); | 1043 __ PushReturnAddressFrom(scratch1()); |
1046 | 1044 |
1047 // Do tail-call to the runtime system. | 1045 // Do tail-call to the runtime system. |
1048 ExternalReference store_ic_property = ExternalReference( | 1046 ExternalReference store_ic_property = ExternalReference( |
1049 IC_Utility(IC::kStorePropertyWithInterceptor), isolate()); | 1047 IC_Utility(IC::kStorePropertyWithInterceptor), isolate()); |
1050 __ TailCallExternalReference(store_ic_property, 3, 1); | 1048 __ TailCallExternalReference(store_ic_property, 3, 1); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1095 __ bind(&miss); | 1093 __ bind(&miss); |
1096 | 1094 |
1097 TailCallBuiltin(masm(), MissBuiltin(kind())); | 1095 TailCallBuiltin(masm(), MissBuiltin(kind())); |
1098 | 1096 |
1099 // Return the generated code. | 1097 // Return the generated code. |
1100 return GetCode(kind(), Code::NORMAL, factory()->empty_string(), POLYMORPHIC); | 1098 return GetCode(kind(), Code::NORMAL, factory()->empty_string(), POLYMORPHIC); |
1101 } | 1099 } |
1102 | 1100 |
1103 | 1101 |
1104 Handle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent( | 1102 Handle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent( |
1105 Handle<JSObject> last, Handle<Name> name) { | 1103 Handle<Name> name) { |
1106 NonexistentFrontend(last, name); | 1104 NonexistentFrontend(name); |
1107 | 1105 |
1108 // Return undefined if maps of the full prototype chain are still the | 1106 // Return undefined if maps of the full prototype chain are still the |
1109 // same and no global property with this name contains a value. | 1107 // same and no global property with this name contains a value. |
1110 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); | 1108 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); |
1111 __ ret(0); | 1109 __ ret(0); |
1112 | 1110 |
1113 // Return the generated code. | 1111 // Return the generated code. |
1114 return GetCode(kind(), Code::FAST, name); | 1112 return GetCode(kind(), Code::FAST, name); |
1115 } | 1113 } |
1116 | 1114 |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1184 } | 1182 } |
1185 __ ret(0); | 1183 __ ret(0); |
1186 } | 1184 } |
1187 | 1185 |
1188 | 1186 |
1189 #undef __ | 1187 #undef __ |
1190 #define __ ACCESS_MASM(masm()) | 1188 #define __ ACCESS_MASM(masm()) |
1191 | 1189 |
1192 | 1190 |
1193 Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( | 1191 Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( |
1194 Handle<GlobalObject> global, Handle<PropertyCell> cell, Handle<Name> name, | 1192 Handle<PropertyCell> cell, Handle<Name> name, bool is_dont_delete) { |
1195 bool is_dont_delete) { | |
1196 Label miss; | 1193 Label miss; |
1197 FrontendHeader(receiver(), global, name, &miss); | 1194 FrontendHeader(receiver(), name, &miss); |
1198 | 1195 |
1199 // Get the value from the cell. | 1196 // Get the value from the cell. |
1200 Register result = StoreIC::ValueRegister(); | 1197 Register result = StoreIC::ValueRegister(); |
1201 __ Move(result, cell); | 1198 __ Move(result, cell); |
1202 __ movp(result, FieldOperand(result, PropertyCell::kValueOffset)); | 1199 __ movp(result, FieldOperand(result, PropertyCell::kValueOffset)); |
1203 | 1200 |
1204 // Check for deleted property if property can actually be deleted. | 1201 // Check for deleted property if property can actually be deleted. |
1205 if (!is_dont_delete) { | 1202 if (!is_dont_delete) { |
1206 __ CompareRoot(result, Heap::kTheHoleValueRootIndex); | 1203 __ CompareRoot(result, Heap::kTheHoleValueRootIndex); |
1207 __ j(equal, &miss); | 1204 __ j(equal, &miss); |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1323 // ----------------------------------- | 1320 // ----------------------------------- |
1324 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); | 1321 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); |
1325 } | 1322 } |
1326 | 1323 |
1327 | 1324 |
1328 #undef __ | 1325 #undef __ |
1329 | 1326 |
1330 } } // namespace v8::internal | 1327 } } // namespace v8::internal |
1331 | 1328 |
1332 #endif // V8_TARGET_ARCH_X64 | 1329 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |