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_X87 | 7 #if V8_TARGET_ARCH_X87 |
8 | 8 |
9 #include "src/codegen.h" | 9 #include "src/codegen.h" |
10 #include "src/ic-inl.h" | 10 #include "src/ic-inl.h" |
(...skipping 399 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
410 } else if (!holder->HasFastProperties() && !holder->IsJSGlobalProxy()) { | 410 } else if (!holder->HasFastProperties() && !holder->IsJSGlobalProxy()) { |
411 GenerateDictionaryNegativeLookup( | 411 GenerateDictionaryNegativeLookup( |
412 masm, miss, holder_reg, name, scratch1(), scratch2()); | 412 masm, miss, holder_reg, name, scratch1(), scratch2()); |
413 } | 413 } |
414 } | 414 } |
415 | 415 |
416 | 416 |
417 // Receiver_reg is preserved on jumps to miss_label, but may be destroyed if | 417 // Receiver_reg is preserved on jumps to miss_label, but may be destroyed if |
418 // store is successful. | 418 // store is successful. |
419 void NamedStoreHandlerCompiler::GenerateStoreTransition( | 419 void NamedStoreHandlerCompiler::GenerateStoreTransition( |
420 MacroAssembler* masm, Handle<JSObject> object, LookupResult* lookup, | 420 MacroAssembler* masm, LookupResult* lookup, Handle<Map> transition, |
421 Handle<Map> transition, Handle<Name> name, Register receiver_reg, | 421 Handle<Name> name, Register receiver_reg, Register storage_reg, |
422 Register storage_reg, Register value_reg, Register scratch1, | 422 Register value_reg, Register scratch1, Register scratch2, Register unused, |
423 Register scratch2, Register unused, Label* miss_label, Label* slow) { | 423 Label* miss_label, Label* slow) { |
424 int descriptor = transition->LastAdded(); | 424 int descriptor = transition->LastAdded(); |
425 DescriptorArray* descriptors = transition->instance_descriptors(); | 425 DescriptorArray* descriptors = transition->instance_descriptors(); |
426 PropertyDetails details = descriptors->GetDetails(descriptor); | 426 PropertyDetails details = descriptors->GetDetails(descriptor); |
427 Representation representation = details.representation(); | 427 Representation representation = details.representation(); |
428 ASSERT(!representation.IsNone()); | 428 ASSERT(!representation.IsNone()); |
429 | 429 |
430 if (details.type() == CONSTANT) { | 430 if (details.type() == CONSTANT) { |
431 Handle<Object> constant(descriptors->GetValue(descriptor), masm->isolate()); | 431 Handle<Object> constant(descriptors->GetValue(descriptor), masm->isolate()); |
432 __ CmpObject(value_reg, constant); | 432 __ CmpObject(value_reg, constant); |
433 __ j(not_equal, miss_label); | 433 __ j(not_equal, miss_label); |
(...skipping 30 matching lines...) Expand all Loading... |
464 | 464 |
465 __ bind(&heap_number); | 465 __ bind(&heap_number); |
466 __ CheckMap(value_reg, masm->isolate()->factory()->heap_number_map(), | 466 __ CheckMap(value_reg, masm->isolate()->factory()->heap_number_map(), |
467 miss_label, DONT_DO_SMI_CHECK); | 467 miss_label, DONT_DO_SMI_CHECK); |
468 __ fld_d(FieldOperand(value_reg, HeapNumber::kValueOffset)); | 468 __ fld_d(FieldOperand(value_reg, HeapNumber::kValueOffset)); |
469 | 469 |
470 __ bind(&do_store); | 470 __ bind(&do_store); |
471 __ fstp_d(FieldOperand(storage_reg, HeapNumber::kValueOffset)); | 471 __ fstp_d(FieldOperand(storage_reg, HeapNumber::kValueOffset)); |
472 } | 472 } |
473 | 473 |
474 // Stub never generated for non-global objects that require access | 474 // Stub never generated for objects that require access checks. |
475 // checks. | 475 ASSERT(!transition->is_access_check_needed()); |
476 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); | |
477 | 476 |
478 // Perform map transition for the receiver if necessary. | 477 // Perform map transition for the receiver if necessary. |
479 if (details.type() == FIELD && | 478 if (details.type() == FIELD && |
480 object->map()->unused_property_fields() == 0) { | 479 Map::cast(transition->GetBackPointer())->unused_property_fields() == 0) { |
481 // The properties must be extended before we can store the value. | 480 // The properties must be extended before we can store the value. |
482 // We jump to a runtime call that extends the properties array. | 481 // We jump to a runtime call that extends the properties array. |
483 __ pop(scratch1); // Return address. | 482 __ pop(scratch1); // Return address. |
484 __ push(receiver_reg); | 483 __ push(receiver_reg); |
485 __ push(Immediate(transition)); | 484 __ push(Immediate(transition)); |
486 __ push(value_reg); | 485 __ push(value_reg); |
487 __ push(scratch1); | 486 __ push(scratch1); |
488 __ TailCallExternalReference( | 487 __ TailCallExternalReference( |
489 ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage), | 488 ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage), |
490 masm->isolate()), | 489 masm->isolate()), |
(...skipping 19 matching lines...) Expand all Loading... |
510 __ ret(0); | 509 __ ret(0); |
511 return; | 510 return; |
512 } | 511 } |
513 | 512 |
514 int index = transition->instance_descriptors()->GetFieldIndex( | 513 int index = transition->instance_descriptors()->GetFieldIndex( |
515 transition->LastAdded()); | 514 transition->LastAdded()); |
516 | 515 |
517 // Adjust for the number of properties stored in the object. Even in the | 516 // Adjust for the number of properties stored in the object. Even in the |
518 // face of a transition we can use the old map here because the size of the | 517 // face of a transition we can use the old map here because the size of the |
519 // object and the number of in-object properties is not going to change. | 518 // object and the number of in-object properties is not going to change. |
520 index -= object->map()->inobject_properties(); | 519 index -= transition->inobject_properties(); |
521 | 520 |
522 SmiCheck smi_check = representation.IsTagged() | 521 SmiCheck smi_check = representation.IsTagged() |
523 ? INLINE_SMI_CHECK : OMIT_SMI_CHECK; | 522 ? INLINE_SMI_CHECK : OMIT_SMI_CHECK; |
524 // TODO(verwaest): Share this code as a code stub. | 523 // TODO(verwaest): Share this code as a code stub. |
525 if (index < 0) { | 524 if (index < 0) { |
526 // Set the property straight into the object. | 525 // Set the property straight into the object. |
527 int offset = object->map()->instance_size() + (index * kPointerSize); | 526 int offset = transition->instance_size() + (index * kPointerSize); |
528 if (representation.IsDouble()) { | 527 if (representation.IsDouble()) { |
529 __ mov(FieldOperand(receiver_reg, offset), storage_reg); | 528 __ mov(FieldOperand(receiver_reg, offset), storage_reg); |
530 } else { | 529 } else { |
531 __ mov(FieldOperand(receiver_reg, offset), value_reg); | 530 __ mov(FieldOperand(receiver_reg, offset), value_reg); |
532 } | 531 } |
533 | 532 |
534 if (!representation.IsSmi()) { | 533 if (!representation.IsSmi()) { |
535 // Update the write barrier for the array address. | 534 // Update the write barrier for the array address. |
536 if (!representation.IsDouble()) { | 535 if (!representation.IsDouble()) { |
537 __ mov(storage_reg, value_reg); | 536 __ mov(storage_reg, value_reg); |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
685 Handle<Code> code) { | 684 Handle<Code> code) { |
686 __ jmp(code, RelocInfo::CODE_TARGET); | 685 __ jmp(code, RelocInfo::CODE_TARGET); |
687 } | 686 } |
688 | 687 |
689 | 688 |
690 #undef __ | 689 #undef __ |
691 #define __ ACCESS_MASM(masm()) | 690 #define __ ACCESS_MASM(masm()) |
692 | 691 |
693 | 692 |
694 Register PropertyHandlerCompiler::CheckPrototypes( | 693 Register PropertyHandlerCompiler::CheckPrototypes( |
695 Register object_reg, Handle<JSObject> holder, Register holder_reg, | 694 Register object_reg, Register holder_reg, Register scratch1, |
696 Register scratch1, Register scratch2, Handle<Name> name, Label* miss, | 695 Register scratch2, Handle<Name> name, Label* miss, |
697 PrototypeCheckType check) { | 696 PrototypeCheckType check) { |
698 Handle<Map> receiver_map(IC::TypeToMap(*type(), isolate())); | 697 Handle<Map> receiver_map(IC::TypeToMap(*type(), isolate())); |
699 | 698 |
700 // Make sure there's no overlap between holder and object registers. | 699 // Make sure there's no overlap between holder and object registers. |
701 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); | 700 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); |
702 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) | 701 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) |
703 && !scratch2.is(scratch1)); | 702 && !scratch2.is(scratch1)); |
704 | 703 |
705 // Keep track of the current object in register reg. | 704 // Keep track of the current object in register reg. |
706 Register reg = object_reg; | 705 Register reg = object_reg; |
707 int depth = 0; | 706 int depth = 0; |
708 | 707 |
709 Handle<JSObject> current = Handle<JSObject>::null(); | 708 Handle<JSObject> current = Handle<JSObject>::null(); |
710 if (type()->IsConstant()) | 709 if (type()->IsConstant()) |
711 current = Handle<JSObject>::cast(type()->AsConstant()->Value()); | 710 current = Handle<JSObject>::cast(type()->AsConstant()->Value()); |
712 Handle<JSObject> prototype = Handle<JSObject>::null(); | 711 Handle<JSObject> prototype = Handle<JSObject>::null(); |
713 Handle<Map> current_map = receiver_map; | 712 Handle<Map> current_map = receiver_map; |
714 Handle<Map> holder_map(holder->map()); | 713 Handle<Map> holder_map(holder()->map()); |
715 // Traverse the prototype chain and check the maps in the prototype chain for | 714 // Traverse the prototype chain and check the maps in the prototype chain for |
716 // fast and global objects or do negative lookup for normal objects. | 715 // fast and global objects or do negative lookup for normal objects. |
717 while (!current_map.is_identical_to(holder_map)) { | 716 while (!current_map.is_identical_to(holder_map)) { |
718 ++depth; | 717 ++depth; |
719 | 718 |
720 // Only global objects and objects that do not require access | 719 // Only global objects and objects that do not require access |
721 // checks are allowed in stubs. | 720 // checks are allowed in stubs. |
722 ASSERT(current_map->IsJSGlobalProxyMap() || | 721 ASSERT(current_map->IsJSGlobalProxyMap() || |
723 !current_map->is_access_check_needed()); | 722 !current_map->is_access_check_needed()); |
724 | 723 |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
817 Label success; | 816 Label success; |
818 __ jmp(&success); | 817 __ jmp(&success); |
819 GenerateRestoreName(masm(), miss, name); | 818 GenerateRestoreName(masm(), miss, name); |
820 TailCallBuiltin(masm(), MissBuiltin(kind())); | 819 TailCallBuiltin(masm(), MissBuiltin(kind())); |
821 __ bind(&success); | 820 __ bind(&success); |
822 } | 821 } |
823 } | 822 } |
824 | 823 |
825 | 824 |
826 Register NamedLoadHandlerCompiler::CallbackFrontend(Register object_reg, | 825 Register NamedLoadHandlerCompiler::CallbackFrontend(Register object_reg, |
827 Handle<JSObject> holder, | |
828 Handle<Name> name, | 826 Handle<Name> name, |
829 Handle<Object> callback) { | 827 Handle<Object> callback) { |
830 Label miss; | 828 Label miss; |
831 | 829 |
832 Register reg = FrontendHeader(object_reg, holder, name, &miss); | 830 Register reg = FrontendHeader(object_reg, name, &miss); |
833 | 831 |
834 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { | 832 if (!holder()->HasFastProperties()) { |
| 833 ASSERT(!holder()->IsGlobalObject()); |
835 ASSERT(!reg.is(scratch2())); | 834 ASSERT(!reg.is(scratch2())); |
836 ASSERT(!reg.is(scratch3())); | 835 ASSERT(!reg.is(scratch3())); |
837 Register dictionary = scratch1(); | 836 Register dictionary = scratch1(); |
838 bool must_preserve_dictionary_reg = reg.is(dictionary); | 837 bool must_preserve_dictionary_reg = reg.is(dictionary); |
839 | 838 |
840 // Load the properties dictionary. | 839 // Load the properties dictionary. |
841 if (must_preserve_dictionary_reg) { | 840 if (must_preserve_dictionary_reg) { |
842 __ push(dictionary); | 841 __ push(dictionary); |
843 } | 842 } |
844 __ mov(dictionary, FieldOperand(reg, JSObject::kPropertiesOffset)); | 843 __ mov(dictionary, FieldOperand(reg, JSObject::kPropertiesOffset)); |
(...skipping 29 matching lines...) Expand all Loading... |
874 __ cmp(scratch3(), callback); | 873 __ cmp(scratch3(), callback); |
875 __ j(not_equal, &miss); | 874 __ j(not_equal, &miss); |
876 } | 875 } |
877 | 876 |
878 FrontendFooter(name, &miss); | 877 FrontendFooter(name, &miss); |
879 return reg; | 878 return reg; |
880 } | 879 } |
881 | 880 |
882 | 881 |
883 void NamedLoadHandlerCompiler::GenerateLoadField( | 882 void NamedLoadHandlerCompiler::GenerateLoadField( |
884 Register reg, Handle<JSObject> holder, FieldIndex field, | 883 Register reg, FieldIndex field, Representation representation) { |
885 Representation representation) { | |
886 if (!reg.is(receiver())) __ mov(receiver(), reg); | 884 if (!reg.is(receiver())) __ mov(receiver(), reg); |
887 LoadFieldStub stub(isolate(), field); | 885 LoadFieldStub stub(isolate(), field); |
888 GenerateTailCall(masm(), stub.GetCode()); | 886 GenerateTailCall(masm(), stub.GetCode()); |
889 } | 887 } |
890 | 888 |
891 | 889 |
892 void NamedLoadHandlerCompiler::GenerateLoadCallback( | 890 void NamedLoadHandlerCompiler::GenerateLoadCallback( |
893 Register reg, Handle<ExecutableAccessorInfo> callback) { | 891 Register reg, Handle<ExecutableAccessorInfo> callback) { |
894 // Insert additional parameters into the stack frame above return address. | 892 // Insert additional parameters into the stack frame above return address. |
895 ASSERT(!scratch3().is(reg)); | 893 ASSERT(!scratch3().is(reg)); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
934 } | 932 } |
935 | 933 |
936 | 934 |
937 void NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) { | 935 void NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) { |
938 // Return the constant value. | 936 // Return the constant value. |
939 __ LoadObject(eax, value); | 937 __ LoadObject(eax, value); |
940 __ ret(0); | 938 __ ret(0); |
941 } | 939 } |
942 | 940 |
943 | 941 |
944 void NamedLoadHandlerCompiler::GenerateLoadInterceptor( | 942 void NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg, |
945 Register holder_reg, Handle<JSObject> interceptor_holder, | 943 LookupResult* lookup, |
946 LookupResult* lookup, Handle<Name> name) { | 944 Handle<Name> name) { |
947 ASSERT(interceptor_holder->HasNamedInterceptor()); | 945 ASSERT(holder()->HasNamedInterceptor()); |
948 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); | 946 ASSERT(!holder()->GetNamedInterceptor()->getter()->IsUndefined()); |
949 | 947 |
950 // So far the most popular follow ups for interceptor loads are FIELD | 948 // So far the most popular follow ups for interceptor loads are FIELD |
951 // and CALLBACKS, so inline only them, other cases may be added | 949 // and CALLBACKS, so inline only them, other cases may be added |
952 // later. | 950 // later. |
953 bool compile_followup_inline = false; | 951 bool compile_followup_inline = false; |
954 if (lookup->IsFound() && lookup->IsCacheable()) { | 952 if (lookup->IsFound() && lookup->IsCacheable()) { |
955 if (lookup->IsField()) { | 953 if (lookup->IsField()) { |
956 compile_followup_inline = true; | 954 compile_followup_inline = true; |
957 } else if (lookup->type() == CALLBACKS && | 955 } else if (lookup->type() == CALLBACKS && |
958 lookup->GetCallbackObject()->IsExecutableAccessorInfo()) { | 956 lookup->GetCallbackObject()->IsExecutableAccessorInfo()) { |
959 Handle<ExecutableAccessorInfo> callback( | 957 Handle<ExecutableAccessorInfo> callback( |
960 ExecutableAccessorInfo::cast(lookup->GetCallbackObject())); | 958 ExecutableAccessorInfo::cast(lookup->GetCallbackObject())); |
961 compile_followup_inline = | 959 compile_followup_inline = |
962 callback->getter() != NULL && | 960 callback->getter() != NULL && |
963 ExecutableAccessorInfo::IsCompatibleReceiverType(isolate(), callback, | 961 ExecutableAccessorInfo::IsCompatibleReceiverType(isolate(), callback, |
964 type()); | 962 type()); |
965 } | 963 } |
966 } | 964 } |
967 | 965 |
968 if (compile_followup_inline) { | 966 if (compile_followup_inline) { |
969 // Compile the interceptor call, followed by inline code to load the | 967 // Compile the interceptor call, followed by inline code to load the |
970 // property from further up the prototype chain if the call fails. | 968 // property from further up the prototype chain if the call fails. |
971 // Check that the maps haven't changed. | 969 // Check that the maps haven't changed. |
972 ASSERT(holder_reg.is(receiver()) || holder_reg.is(scratch1())); | 970 ASSERT(holder_reg.is(receiver()) || holder_reg.is(scratch1())); |
973 | 971 |
974 // Preserve the receiver register explicitly whenever it is different from | 972 // Preserve the receiver register explicitly whenever it is different from |
975 // the holder and it is needed should the interceptor return without any | 973 // the holder and it is needed should the interceptor return without any |
976 // result. The CALLBACKS case needs the receiver to be passed into C++ code, | 974 // result. The CALLBACKS case needs the receiver to be passed into C++ code, |
977 // the FIELD case might cause a miss during the prototype check. | 975 // the FIELD case might cause a miss during the prototype check. |
978 bool must_perfrom_prototype_check = *interceptor_holder != lookup->holder(); | 976 bool must_perfrom_prototype_check = *holder() != lookup->holder(); |
979 bool must_preserve_receiver_reg = !receiver().is(holder_reg) && | 977 bool must_preserve_receiver_reg = !receiver().is(holder_reg) && |
980 (lookup->type() == CALLBACKS || must_perfrom_prototype_check); | 978 (lookup->type() == CALLBACKS || must_perfrom_prototype_check); |
981 | 979 |
982 // Save necessary data before invoking an interceptor. | 980 // Save necessary data before invoking an interceptor. |
983 // Requires a frame to make GC aware of pushed pointers. | 981 // Requires a frame to make GC aware of pushed pointers. |
984 { | 982 { |
985 FrameScope frame_scope(masm(), StackFrame::INTERNAL); | 983 FrameScope frame_scope(masm(), StackFrame::INTERNAL); |
986 | 984 |
987 if (must_preserve_receiver_reg) { | 985 if (must_preserve_receiver_reg) { |
988 __ push(receiver()); | 986 __ push(receiver()); |
989 } | 987 } |
990 __ push(holder_reg); | 988 __ push(holder_reg); |
991 __ push(this->name()); | 989 __ push(this->name()); |
992 | 990 |
993 // Invoke an interceptor. Note: map checks from receiver to | 991 // Invoke an interceptor. Note: map checks from receiver to |
994 // interceptor's holder has been compiled before (see a caller | 992 // interceptor's holder has been compiled before (see a caller |
995 // of this method.) | 993 // of this method.) |
996 CompileCallLoadPropertyWithInterceptor( | 994 CompileCallLoadPropertyWithInterceptor( |
997 masm(), receiver(), holder_reg, this->name(), interceptor_holder, | 995 masm(), receiver(), holder_reg, this->name(), holder(), |
998 IC::kLoadPropertyWithInterceptorOnly); | 996 IC::kLoadPropertyWithInterceptorOnly); |
999 | 997 |
1000 // Check if interceptor provided a value for property. If it's | 998 // Check if interceptor provided a value for property. If it's |
1001 // the case, return immediately. | 999 // the case, return immediately. |
1002 Label interceptor_failed; | 1000 Label interceptor_failed; |
1003 __ cmp(eax, factory()->no_interceptor_result_sentinel()); | 1001 __ cmp(eax, factory()->no_interceptor_result_sentinel()); |
1004 __ j(equal, &interceptor_failed); | 1002 __ j(equal, &interceptor_failed); |
1005 frame_scope.GenerateLeaveFrame(); | 1003 frame_scope.GenerateLeaveFrame(); |
1006 __ ret(0); | 1004 __ ret(0); |
1007 | 1005 |
1008 // Clobber registers when generating debug-code to provoke errors. | 1006 // Clobber registers when generating debug-code to provoke errors. |
1009 __ bind(&interceptor_failed); | 1007 __ bind(&interceptor_failed); |
1010 if (FLAG_debug_code) { | 1008 if (FLAG_debug_code) { |
1011 __ mov(receiver(), Immediate(BitCast<int32_t>(kZapValue))); | 1009 __ mov(receiver(), Immediate(BitCast<int32_t>(kZapValue))); |
1012 __ mov(holder_reg, Immediate(BitCast<int32_t>(kZapValue))); | 1010 __ mov(holder_reg, Immediate(BitCast<int32_t>(kZapValue))); |
1013 __ mov(this->name(), Immediate(BitCast<int32_t>(kZapValue))); | 1011 __ mov(this->name(), Immediate(BitCast<int32_t>(kZapValue))); |
1014 } | 1012 } |
1015 | 1013 |
1016 __ pop(this->name()); | 1014 __ pop(this->name()); |
1017 __ pop(holder_reg); | 1015 __ pop(holder_reg); |
1018 if (must_preserve_receiver_reg) { | 1016 if (must_preserve_receiver_reg) { |
1019 __ pop(receiver()); | 1017 __ pop(receiver()); |
1020 } | 1018 } |
1021 | 1019 |
1022 // Leave the internal frame. | 1020 // Leave the internal frame. |
1023 } | 1021 } |
1024 | 1022 |
1025 GenerateLoadPostInterceptor(holder_reg, interceptor_holder, name, lookup); | 1023 GenerateLoadPostInterceptor(holder_reg, name, lookup); |
1026 } else { // !compile_followup_inline | 1024 } else { // !compile_followup_inline |
1027 // Call the runtime system to load the interceptor. | 1025 // Call the runtime system to load the interceptor. |
1028 // Check that the maps haven't changed. | 1026 // Check that the maps haven't changed. |
1029 __ pop(scratch2()); // save old return address | 1027 __ pop(scratch2()); // save old return address |
1030 PushInterceptorArguments(masm(), receiver(), holder_reg, | 1028 PushInterceptorArguments(masm(), receiver(), holder_reg, this->name(), |
1031 this->name(), interceptor_holder); | 1029 holder()); |
1032 __ push(scratch2()); // restore old return address | 1030 __ push(scratch2()); // restore old return address |
1033 | 1031 |
1034 ExternalReference ref = | 1032 ExternalReference ref = |
1035 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptor), | 1033 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptor), |
1036 isolate()); | 1034 isolate()); |
1037 __ TailCallExternalReference( | 1035 __ TailCallExternalReference( |
1038 ref, NamedLoadHandlerCompiler::kInterceptorArgsLength, 1); | 1036 ref, NamedLoadHandlerCompiler::kInterceptorArgsLength, 1); |
1039 } | 1037 } |
1040 } | 1038 } |
1041 | 1039 |
1042 | 1040 |
1043 Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( | 1041 Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( |
1044 Handle<JSObject> object, Handle<JSObject> holder, Handle<Name> name, | 1042 Handle<JSObject> object, Handle<Name> name, |
1045 Handle<ExecutableAccessorInfo> callback) { | 1043 Handle<ExecutableAccessorInfo> callback) { |
1046 Register holder_reg = Frontend(receiver(), holder, name); | 1044 Register holder_reg = Frontend(receiver(), name); |
1047 | 1045 |
1048 __ pop(scratch1()); // remove the return address | 1046 __ pop(scratch1()); // remove the return address |
1049 __ push(receiver()); | 1047 __ push(receiver()); |
1050 __ push(holder_reg); | 1048 __ push(holder_reg); |
1051 __ Push(callback); | 1049 __ Push(callback); |
1052 __ Push(name); | 1050 __ Push(name); |
1053 __ push(value()); | 1051 __ push(value()); |
1054 __ push(scratch1()); // restore return address | 1052 __ push(scratch1()); // restore return address |
1055 | 1053 |
1056 // Do tail-call to the runtime system. | 1054 // Do tail-call to the runtime system. |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1106 } | 1104 } |
1107 __ ret(0); | 1105 __ ret(0); |
1108 } | 1106 } |
1109 | 1107 |
1110 | 1108 |
1111 #undef __ | 1109 #undef __ |
1112 #define __ ACCESS_MASM(masm()) | 1110 #define __ ACCESS_MASM(masm()) |
1113 | 1111 |
1114 | 1112 |
1115 Handle<Code> NamedStoreHandlerCompiler::CompileStoreInterceptor( | 1113 Handle<Code> NamedStoreHandlerCompiler::CompileStoreInterceptor( |
1116 Handle<JSObject> object, Handle<Name> name) { | 1114 Handle<Name> name) { |
1117 __ pop(scratch1()); // remove the return address | 1115 __ pop(scratch1()); // remove the return address |
1118 __ push(receiver()); | 1116 __ push(receiver()); |
1119 __ push(this->name()); | 1117 __ push(this->name()); |
1120 __ push(value()); | 1118 __ push(value()); |
1121 __ push(scratch1()); // restore return address | 1119 __ push(scratch1()); // restore return address |
1122 | 1120 |
1123 // Do tail-call to the runtime system. | 1121 // Do tail-call to the runtime system. |
1124 ExternalReference store_ic_property = ExternalReference( | 1122 ExternalReference store_ic_property = ExternalReference( |
1125 IC_Utility(IC::kStorePropertyWithInterceptor), isolate()); | 1123 IC_Utility(IC::kStorePropertyWithInterceptor), isolate()); |
1126 __ TailCallExternalReference(store_ic_property, 3, 1); | 1124 __ TailCallExternalReference(store_ic_property, 3, 1); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1164 } | 1162 } |
1165 __ bind(&miss); | 1163 __ bind(&miss); |
1166 TailCallBuiltin(masm(), MissBuiltin(kind())); | 1164 TailCallBuiltin(masm(), MissBuiltin(kind())); |
1167 | 1165 |
1168 // Return the generated code. | 1166 // Return the generated code. |
1169 return GetCode(kind(), Code::NORMAL, factory()->empty_string(), POLYMORPHIC); | 1167 return GetCode(kind(), Code::NORMAL, factory()->empty_string(), POLYMORPHIC); |
1170 } | 1168 } |
1171 | 1169 |
1172 | 1170 |
1173 Handle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent( | 1171 Handle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent( |
1174 Handle<JSObject> last, Handle<Name> name) { | 1172 Handle<Name> name) { |
1175 NonexistentFrontend(last, name); | 1173 NonexistentFrontend(name); |
1176 | 1174 |
1177 // Return undefined if maps of the full prototype chain are still the | 1175 // Return undefined if maps of the full prototype chain are still the |
1178 // same and no global property with this name contains a value. | 1176 // same and no global property with this name contains a value. |
1179 __ mov(eax, isolate()->factory()->undefined_value()); | 1177 __ mov(eax, isolate()->factory()->undefined_value()); |
1180 __ ret(0); | 1178 __ ret(0); |
1181 | 1179 |
1182 // Return the generated code. | 1180 // Return the generated code. |
1183 return GetCode(kind(), Code::FAST, name); | 1181 return GetCode(kind(), Code::FAST, name); |
1184 } | 1182 } |
1185 | 1183 |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1248 } | 1246 } |
1249 __ ret(0); | 1247 __ ret(0); |
1250 } | 1248 } |
1251 | 1249 |
1252 | 1250 |
1253 #undef __ | 1251 #undef __ |
1254 #define __ ACCESS_MASM(masm()) | 1252 #define __ ACCESS_MASM(masm()) |
1255 | 1253 |
1256 | 1254 |
1257 Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( | 1255 Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( |
1258 Handle<GlobalObject> global, Handle<PropertyCell> cell, Handle<Name> name, | 1256 Handle<PropertyCell> cell, Handle<Name> name, bool is_dont_delete) { |
1259 bool is_dont_delete) { | |
1260 Label miss; | 1257 Label miss; |
1261 | 1258 |
1262 FrontendHeader(receiver(), global, name, &miss); | 1259 FrontendHeader(receiver(), name, &miss); |
1263 // Get the value from the cell. | 1260 // Get the value from the cell. |
1264 Register result = StoreIC::ValueRegister(); | 1261 Register result = StoreIC::ValueRegister(); |
1265 if (masm()->serializer_enabled()) { | 1262 if (masm()->serializer_enabled()) { |
1266 __ mov(result, Immediate(cell)); | 1263 __ mov(result, Immediate(cell)); |
1267 __ mov(result, FieldOperand(result, PropertyCell::kValueOffset)); | 1264 __ mov(result, FieldOperand(result, PropertyCell::kValueOffset)); |
1268 } else { | 1265 } else { |
1269 __ mov(result, Operand::ForCell(cell)); | 1266 __ mov(result, Operand::ForCell(cell)); |
1270 } | 1267 } |
1271 | 1268 |
1272 // Check for deleted property if property can actually be deleted. | 1269 // Check for deleted property if property can actually be deleted. |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1393 // ----------------------------------- | 1390 // ----------------------------------- |
1394 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); | 1391 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); |
1395 } | 1392 } |
1396 | 1393 |
1397 | 1394 |
1398 #undef __ | 1395 #undef __ |
1399 | 1396 |
1400 } } // namespace v8::internal | 1397 } } // namespace v8::internal |
1401 | 1398 |
1402 #endif // V8_TARGET_ARCH_X87 | 1399 #endif // V8_TARGET_ARCH_X87 |
OLD | NEW |