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 615 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
626 Handle<Code> code) { | 626 Handle<Code> code) { |
627 __ jmp(code, RelocInfo::CODE_TARGET); | 627 __ jmp(code, RelocInfo::CODE_TARGET); |
628 } | 628 } |
629 | 629 |
630 | 630 |
631 #undef __ | 631 #undef __ |
632 #define __ ACCESS_MASM((masm())) | 632 #define __ ACCESS_MASM((masm())) |
633 | 633 |
634 | 634 |
635 Register PropertyHandlerCompiler::CheckPrototypes( | 635 Register PropertyHandlerCompiler::CheckPrototypes( |
636 Handle<HeapType> type, Register object_reg, Handle<JSObject> holder, | 636 Register object_reg, Handle<JSObject> holder, Register holder_reg, |
637 Register holder_reg, Register scratch1, Register scratch2, | 637 Register scratch1, Register scratch2, Handle<Name> name, Label* miss, |
638 Handle<Name> name, Label* miss, PrototypeCheckType check) { | 638 PrototypeCheckType check) { |
639 Handle<Map> receiver_map(IC::TypeToMap(*type, isolate())); | 639 Handle<Map> receiver_map(IC::TypeToMap(*type(), isolate())); |
640 | 640 |
641 // Make sure there's no overlap between holder and object registers. | 641 // Make sure there's no overlap between holder and object registers. |
642 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); | 642 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); |
643 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) | 643 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) |
644 && !scratch2.is(scratch1)); | 644 && !scratch2.is(scratch1)); |
645 | 645 |
646 // Keep track of the current object in register reg. On the first | 646 // Keep track of the current object in register reg. On the first |
647 // iteration, reg is an alias for object_reg, on later iterations, | 647 // iteration, reg is an alias for object_reg, on later iterations, |
648 // it is an alias for holder_reg. | 648 // it is an alias for holder_reg. |
649 Register reg = object_reg; | 649 Register reg = object_reg; |
650 int depth = 0; | 650 int depth = 0; |
651 | 651 |
652 Handle<JSObject> current = Handle<JSObject>::null(); | 652 Handle<JSObject> current = Handle<JSObject>::null(); |
653 if (type->IsConstant()) { | 653 if (type()->IsConstant()) { |
654 current = Handle<JSObject>::cast(type->AsConstant()->Value()); | 654 current = Handle<JSObject>::cast(type()->AsConstant()->Value()); |
655 } | 655 } |
656 Handle<JSObject> prototype = Handle<JSObject>::null(); | 656 Handle<JSObject> prototype = Handle<JSObject>::null(); |
657 Handle<Map> current_map = receiver_map; | 657 Handle<Map> current_map = receiver_map; |
658 Handle<Map> holder_map(holder->map()); | 658 Handle<Map> holder_map(holder->map()); |
659 // Traverse the prototype chain and check the maps in the prototype chain for | 659 // 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. | 660 // fast and global objects or do negative lookup for normal objects. |
661 while (!current_map.is_identical_to(holder_map)) { | 661 while (!current_map.is_identical_to(holder_map)) { |
662 ++depth; | 662 ++depth; |
663 | 663 |
664 // Only global objects and objects that do not require access | 664 // Only global objects and objects that do not require access |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
758 if (!miss->is_unused()) { | 758 if (!miss->is_unused()) { |
759 Label success; | 759 Label success; |
760 __ jmp(&success); | 760 __ jmp(&success); |
761 GenerateRestoreName(masm(), miss, name); | 761 GenerateRestoreName(masm(), miss, name); |
762 TailCallBuiltin(masm(), MissBuiltin(kind())); | 762 TailCallBuiltin(masm(), MissBuiltin(kind())); |
763 __ bind(&success); | 763 __ bind(&success); |
764 } | 764 } |
765 } | 765 } |
766 | 766 |
767 | 767 |
768 Register NamedLoadHandlerCompiler::CallbackFrontend(Handle<HeapType> type, | 768 Register NamedLoadHandlerCompiler::CallbackFrontend(Register object_reg, |
769 Register object_reg, | |
770 Handle<JSObject> holder, | 769 Handle<JSObject> holder, |
771 Handle<Name> name, | 770 Handle<Name> name, |
772 Handle<Object> callback) { | 771 Handle<Object> callback) { |
773 Label miss; | 772 Label miss; |
774 | 773 |
775 Register reg = FrontendHeader(type, object_reg, holder, name, &miss); | 774 Register reg = FrontendHeader(object_reg, holder, name, &miss); |
776 | 775 |
777 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { | 776 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { |
778 ASSERT(!reg.is(scratch2())); | 777 ASSERT(!reg.is(scratch2())); |
779 ASSERT(!reg.is(scratch3())); | 778 ASSERT(!reg.is(scratch3())); |
780 ASSERT(!reg.is(scratch4())); | 779 ASSERT(!reg.is(scratch4())); |
781 | 780 |
782 // Load the properties dictionary. | 781 // Load the properties dictionary. |
783 Register dictionary = scratch4(); | 782 Register dictionary = scratch4(); |
784 __ movp(dictionary, FieldOperand(reg, JSObject::kPropertiesOffset)); | 783 __ movp(dictionary, FieldOperand(reg, JSObject::kPropertiesOffset)); |
785 | 784 |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
868 | 867 |
869 | 868 |
870 void NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) { | 869 void NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) { |
871 // Return the constant value. | 870 // Return the constant value. |
872 __ Move(rax, value); | 871 __ Move(rax, value); |
873 __ ret(0); | 872 __ ret(0); |
874 } | 873 } |
875 | 874 |
876 | 875 |
877 void NamedLoadHandlerCompiler::GenerateLoadInterceptor( | 876 void NamedLoadHandlerCompiler::GenerateLoadInterceptor( |
878 Register holder_reg, Handle<Object> object, | 877 Register holder_reg, Handle<JSObject> interceptor_holder, |
879 Handle<JSObject> interceptor_holder, LookupResult* lookup, | 878 LookupResult* lookup, Handle<Name> name) { |
880 Handle<Name> name) { | |
881 ASSERT(interceptor_holder->HasNamedInterceptor()); | 879 ASSERT(interceptor_holder->HasNamedInterceptor()); |
882 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); | 880 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); |
883 | 881 |
884 // So far the most popular follow ups for interceptor loads are FIELD | 882 // So far the most popular follow ups for interceptor loads are FIELD |
885 // and CALLBACKS, so inline only them, other cases may be added | 883 // and CALLBACKS, so inline only them, other cases may be added |
886 // later. | 884 // later. |
887 bool compile_followup_inline = false; | 885 bool compile_followup_inline = false; |
888 if (lookup->IsFound() && lookup->IsCacheable()) { | 886 if (lookup->IsFound() && lookup->IsCacheable()) { |
889 if (lookup->IsField()) { | 887 if (lookup->IsField()) { |
890 compile_followup_inline = true; | 888 compile_followup_inline = true; |
891 } else if (lookup->type() == CALLBACKS && | 889 } else if (lookup->type() == CALLBACKS && |
892 lookup->GetCallbackObject()->IsExecutableAccessorInfo()) { | 890 lookup->GetCallbackObject()->IsExecutableAccessorInfo()) { |
893 ExecutableAccessorInfo* callback = | 891 Handle<ExecutableAccessorInfo> callback( |
894 ExecutableAccessorInfo::cast(lookup->GetCallbackObject()); | 892 ExecutableAccessorInfo::cast(lookup->GetCallbackObject())); |
895 compile_followup_inline = callback->getter() != NULL && | 893 compile_followup_inline = |
896 callback->IsCompatibleReceiver(*object); | 894 callback->getter() != NULL && |
| 895 ExecutableAccessorInfo::IsCompatibleReceiverType(isolate(), callback, |
| 896 type()); |
897 } | 897 } |
898 } | 898 } |
899 | 899 |
900 if (compile_followup_inline) { | 900 if (compile_followup_inline) { |
901 // Compile the interceptor call, followed by inline code to load the | 901 // Compile the interceptor call, followed by inline code to load the |
902 // property from further up the prototype chain if the call fails. | 902 // property from further up the prototype chain if the call fails. |
903 // Check that the maps haven't changed. | 903 // Check that the maps haven't changed. |
904 ASSERT(holder_reg.is(receiver()) || holder_reg.is(scratch1())); | 904 ASSERT(holder_reg.is(receiver()) || holder_reg.is(scratch1())); |
905 | 905 |
906 // Preserve the receiver register explicitly whenever it is different from | 906 // Preserve the receiver register explicitly whenever it is different from |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
960 IC_Utility(IC::kLoadPropertyWithInterceptor), isolate()); | 960 IC_Utility(IC::kLoadPropertyWithInterceptor), isolate()); |
961 __ TailCallExternalReference( | 961 __ TailCallExternalReference( |
962 ref, NamedLoadHandlerCompiler::kInterceptorArgsLength, 1); | 962 ref, NamedLoadHandlerCompiler::kInterceptorArgsLength, 1); |
963 } | 963 } |
964 } | 964 } |
965 | 965 |
966 | 966 |
967 Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( | 967 Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( |
968 Handle<JSObject> object, Handle<JSObject> holder, Handle<Name> name, | 968 Handle<JSObject> object, Handle<JSObject> holder, Handle<Name> name, |
969 Handle<ExecutableAccessorInfo> callback) { | 969 Handle<ExecutableAccessorInfo> callback) { |
970 Register holder_reg = | 970 Register holder_reg = Frontend(receiver(), holder, name); |
971 Frontend(IC::CurrentTypeOf(object, isolate()), receiver(), holder, name); | |
972 | 971 |
973 __ PopReturnAddressTo(scratch1()); | 972 __ PopReturnAddressTo(scratch1()); |
974 __ Push(receiver()); | 973 __ Push(receiver()); |
975 __ Push(holder_reg); | 974 __ Push(holder_reg); |
976 __ Push(callback); // callback info | 975 __ Push(callback); // callback info |
977 __ Push(name); | 976 __ Push(name); |
978 __ Push(value()); | 977 __ Push(value()); |
979 __ PushReturnAddressFrom(scratch1()); | 978 __ PushReturnAddressFrom(scratch1()); |
980 | 979 |
981 // Do tail-call to the runtime system. | 980 // Do tail-call to the runtime system. |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1096 __ bind(&miss); | 1095 __ bind(&miss); |
1097 | 1096 |
1098 TailCallBuiltin(masm(), MissBuiltin(kind())); | 1097 TailCallBuiltin(masm(), MissBuiltin(kind())); |
1099 | 1098 |
1100 // Return the generated code. | 1099 // Return the generated code. |
1101 return GetCode(kind(), Code::NORMAL, factory()->empty_string(), POLYMORPHIC); | 1100 return GetCode(kind(), Code::NORMAL, factory()->empty_string(), POLYMORPHIC); |
1102 } | 1101 } |
1103 | 1102 |
1104 | 1103 |
1105 Handle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent( | 1104 Handle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent( |
1106 Handle<HeapType> type, Handle<JSObject> last, Handle<Name> name) { | 1105 Handle<JSObject> last, Handle<Name> name) { |
1107 NonexistentFrontend(type, last, name); | 1106 NonexistentFrontend(last, name); |
1108 | 1107 |
1109 // Return undefined if maps of the full prototype chain are still the | 1108 // Return undefined if maps of the full prototype chain are still the |
1110 // same and no global property with this name contains a value. | 1109 // same and no global property with this name contains a value. |
1111 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); | 1110 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); |
1112 __ ret(0); | 1111 __ ret(0); |
1113 | 1112 |
1114 // Return the generated code. | 1113 // Return the generated code. |
1115 return GetCode(kind(), Code::FAST, name); | 1114 return GetCode(kind(), Code::FAST, name); |
1116 } | 1115 } |
1117 | 1116 |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1185 } | 1184 } |
1186 __ ret(0); | 1185 __ ret(0); |
1187 } | 1186 } |
1188 | 1187 |
1189 | 1188 |
1190 #undef __ | 1189 #undef __ |
1191 #define __ ACCESS_MASM(masm()) | 1190 #define __ ACCESS_MASM(masm()) |
1192 | 1191 |
1193 | 1192 |
1194 Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( | 1193 Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( |
1195 Handle<HeapType> type, Handle<GlobalObject> global, | 1194 Handle<GlobalObject> global, Handle<PropertyCell> cell, Handle<Name> name, |
1196 Handle<PropertyCell> cell, Handle<Name> name, bool is_dont_delete) { | 1195 bool is_dont_delete) { |
1197 Label miss; | 1196 Label miss; |
1198 // TODO(verwaest): Directly store to rax. Currently we cannot do this, since | 1197 FrontendHeader(receiver(), global, name, &miss); |
1199 // rax is used as receiver(), which we would otherwise clobber before a | |
1200 // potential miss. | |
1201 FrontendHeader(type, receiver(), global, name, &miss); | |
1202 | 1198 |
1203 // Get the value from the cell. | 1199 // Get the value from the cell. |
1204 __ Move(rbx, cell); | 1200 Register result = StoreIC::ValueRegister(); |
1205 __ movp(rbx, FieldOperand(rbx, PropertyCell::kValueOffset)); | 1201 __ Move(result, cell); |
| 1202 __ movp(result, FieldOperand(result, PropertyCell::kValueOffset)); |
1206 | 1203 |
1207 // Check for deleted property if property can actually be deleted. | 1204 // Check for deleted property if property can actually be deleted. |
1208 if (!is_dont_delete) { | 1205 if (!is_dont_delete) { |
1209 __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex); | 1206 __ CompareRoot(result, Heap::kTheHoleValueRootIndex); |
1210 __ j(equal, &miss); | 1207 __ j(equal, &miss); |
1211 } else if (FLAG_debug_code) { | 1208 } else if (FLAG_debug_code) { |
1212 __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex); | 1209 __ CompareRoot(result, Heap::kTheHoleValueRootIndex); |
1213 __ Check(not_equal, kDontDeleteCellsCannotContainTheHole); | 1210 __ Check(not_equal, kDontDeleteCellsCannotContainTheHole); |
1214 } | 1211 } |
1215 | 1212 |
1216 Counters* counters = isolate()->counters(); | 1213 Counters* counters = isolate()->counters(); |
1217 __ IncrementCounter(counters->named_load_global_stub(), 1); | 1214 __ IncrementCounter(counters->named_load_global_stub(), 1); |
1218 __ movp(rax, rbx); | |
1219 __ ret(0); | 1215 __ ret(0); |
1220 | 1216 |
1221 FrontendFooter(name, &miss); | 1217 FrontendFooter(name, &miss); |
1222 | 1218 |
1223 // Return the generated code. | 1219 // Return the generated code. |
1224 return GetCode(kind(), Code::NORMAL, name); | 1220 return GetCode(kind(), Code::NORMAL, name); |
1225 } | 1221 } |
1226 | 1222 |
1227 | 1223 |
1228 Handle<Code> PropertyICCompiler::CompilePolymorphic(TypeHandleList* types, | 1224 Handle<Code> PropertyICCompiler::CompilePolymorphic(TypeHandleList* types, |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1321 // ----------------------------------- | 1317 // ----------------------------------- |
1322 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); | 1318 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); |
1323 } | 1319 } |
1324 | 1320 |
1325 | 1321 |
1326 #undef __ | 1322 #undef __ |
1327 | 1323 |
1328 } } // namespace v8::internal | 1324 } } // namespace v8::internal |
1329 | 1325 |
1330 #endif // V8_TARGET_ARCH_X64 | 1326 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |