OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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_ARM64 | 7 #if V8_TARGET_ARCH_ARM64 |
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 664 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
675 Handle<Code> code) { | 675 Handle<Code> code) { |
676 __ Jump(code, RelocInfo::CODE_TARGET); | 676 __ Jump(code, RelocInfo::CODE_TARGET); |
677 } | 677 } |
678 | 678 |
679 | 679 |
680 #undef __ | 680 #undef __ |
681 #define __ ACCESS_MASM(masm()) | 681 #define __ ACCESS_MASM(masm()) |
682 | 682 |
683 | 683 |
684 Register PropertyHandlerCompiler::CheckPrototypes( | 684 Register PropertyHandlerCompiler::CheckPrototypes( |
685 Handle<HeapType> type, Register object_reg, Handle<JSObject> holder, | 685 Register object_reg, Handle<JSObject> holder, Register holder_reg, |
686 Register holder_reg, Register scratch1, Register scratch2, | 686 Register scratch1, Register scratch2, Handle<Name> name, Label* miss, |
687 Handle<Name> name, Label* miss, PrototypeCheckType check) { | 687 PrototypeCheckType check) { |
688 Handle<Map> receiver_map(IC::TypeToMap(*type, isolate())); | 688 Handle<Map> receiver_map(IC::TypeToMap(*type(), isolate())); |
689 | 689 |
690 // object_reg and holder_reg registers can alias. | 690 // object_reg and holder_reg registers can alias. |
691 ASSERT(!AreAliased(object_reg, scratch1, scratch2)); | 691 ASSERT(!AreAliased(object_reg, scratch1, scratch2)); |
692 ASSERT(!AreAliased(holder_reg, scratch1, scratch2)); | 692 ASSERT(!AreAliased(holder_reg, scratch1, scratch2)); |
693 | 693 |
694 // Keep track of the current object in register reg. | 694 // Keep track of the current object in register reg. |
695 Register reg = object_reg; | 695 Register reg = object_reg; |
696 int depth = 0; | 696 int depth = 0; |
697 | 697 |
698 Handle<JSObject> current = Handle<JSObject>::null(); | 698 Handle<JSObject> current = Handle<JSObject>::null(); |
699 if (type->IsConstant()) { | 699 if (type()->IsConstant()) { |
700 current = Handle<JSObject>::cast(type->AsConstant()->Value()); | 700 current = Handle<JSObject>::cast(type()->AsConstant()->Value()); |
701 } | 701 } |
702 Handle<JSObject> prototype = Handle<JSObject>::null(); | 702 Handle<JSObject> prototype = Handle<JSObject>::null(); |
703 Handle<Map> current_map = receiver_map; | 703 Handle<Map> current_map = receiver_map; |
704 Handle<Map> holder_map(holder->map()); | 704 Handle<Map> holder_map(holder->map()); |
705 // Traverse the prototype chain and check the maps in the prototype chain for | 705 // Traverse the prototype chain and check the maps in the prototype chain for |
706 // fast and global objects or do negative lookup for normal objects. | 706 // fast and global objects or do negative lookup for normal objects. |
707 while (!current_map.is_identical_to(holder_map)) { | 707 while (!current_map.is_identical_to(holder_map)) { |
708 ++depth; | 708 ++depth; |
709 | 709 |
710 // Only global objects and objects that do not require access | 710 // Only global objects and objects that do not require access |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
810 __ B(&success); | 810 __ B(&success); |
811 | 811 |
812 GenerateRestoreName(masm(), miss, name); | 812 GenerateRestoreName(masm(), miss, name); |
813 TailCallBuiltin(masm(), MissBuiltin(kind())); | 813 TailCallBuiltin(masm(), MissBuiltin(kind())); |
814 | 814 |
815 __ Bind(&success); | 815 __ Bind(&success); |
816 } | 816 } |
817 } | 817 } |
818 | 818 |
819 | 819 |
820 Register NamedLoadHandlerCompiler::CallbackFrontend(Handle<HeapType> type, | 820 Register NamedLoadHandlerCompiler::CallbackFrontend(Register object_reg, |
821 Register object_reg, | |
822 Handle<JSObject> holder, | 821 Handle<JSObject> holder, |
823 Handle<Name> name, | 822 Handle<Name> name, |
824 Handle<Object> callback) { | 823 Handle<Object> callback) { |
825 Label miss; | 824 Label miss; |
826 | 825 |
827 Register reg = FrontendHeader(type, object_reg, holder, name, &miss); | 826 Register reg = FrontendHeader(object_reg, holder, name, &miss); |
828 // FrontendHeader can return its result into scratch1() so do not | 827 // FrontendHeader can return its result into scratch1() so do not |
829 // use it. | 828 // use it. |
830 Register scratch2 = this->scratch2(); | 829 Register scratch2 = this->scratch2(); |
831 Register scratch3 = this->scratch3(); | 830 Register scratch3 = this->scratch3(); |
832 Register dictionary = this->scratch4(); | 831 Register dictionary = this->scratch4(); |
833 ASSERT(!AreAliased(reg, scratch2, scratch3, dictionary)); | 832 ASSERT(!AreAliased(reg, scratch2, scratch3, dictionary)); |
834 | 833 |
835 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { | 834 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { |
836 // Load the properties dictionary. | 835 // Load the properties dictionary. |
837 __ Ldr(dictionary, FieldMemOperand(reg, JSObject::kPropertiesOffset)); | 836 __ Ldr(dictionary, FieldMemOperand(reg, JSObject::kPropertiesOffset)); |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
927 ExternalReference::Type type = ExternalReference::DIRECT_GETTER_CALL; | 926 ExternalReference::Type type = ExternalReference::DIRECT_GETTER_CALL; |
928 ExternalReference ref = ExternalReference(&fun, type, isolate()); | 927 ExternalReference ref = ExternalReference(&fun, type, isolate()); |
929 __ Mov(getter_address_reg, ref); | 928 __ Mov(getter_address_reg, ref); |
930 | 929 |
931 CallApiGetterStub stub(isolate()); | 930 CallApiGetterStub stub(isolate()); |
932 __ TailCallStub(&stub); | 931 __ TailCallStub(&stub); |
933 } | 932 } |
934 | 933 |
935 | 934 |
936 void NamedLoadHandlerCompiler::GenerateLoadInterceptor( | 935 void NamedLoadHandlerCompiler::GenerateLoadInterceptor( |
937 Register holder_reg, Handle<Object> object, | 936 Register holder_reg, Handle<JSObject> interceptor_holder, |
938 Handle<JSObject> interceptor_holder, LookupResult* lookup, | 937 LookupResult* lookup, Handle<Name> name) { |
939 Handle<Name> name) { | |
940 ASSERT(!AreAliased(receiver(), this->name(), | 938 ASSERT(!AreAliased(receiver(), this->name(), |
941 scratch1(), scratch2(), scratch3())); | 939 scratch1(), scratch2(), scratch3())); |
942 ASSERT(interceptor_holder->HasNamedInterceptor()); | 940 ASSERT(interceptor_holder->HasNamedInterceptor()); |
943 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); | 941 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); |
944 | 942 |
945 // So far the most popular follow ups for interceptor loads are FIELD | 943 // So far the most popular follow ups for interceptor loads are FIELD |
946 // and CALLBACKS, so inline only them, other cases may be added later. | 944 // and CALLBACKS, so inline only them, other cases may be added later. |
947 bool compile_followup_inline = false; | 945 bool compile_followup_inline = false; |
948 if (lookup->IsFound() && lookup->IsCacheable()) { | 946 if (lookup->IsFound() && lookup->IsCacheable()) { |
949 if (lookup->IsField()) { | 947 if (lookup->IsField()) { |
950 compile_followup_inline = true; | 948 compile_followup_inline = true; |
951 } else if (lookup->type() == CALLBACKS && | 949 } else if (lookup->type() == CALLBACKS && |
952 lookup->GetCallbackObject()->IsExecutableAccessorInfo()) { | 950 lookup->GetCallbackObject()->IsExecutableAccessorInfo()) { |
953 ExecutableAccessorInfo* callback = | 951 ExecutableAccessorInfo* callback = |
954 ExecutableAccessorInfo::cast(lookup->GetCallbackObject()); | 952 ExecutableAccessorInfo::cast(lookup->GetCallbackObject()); |
955 compile_followup_inline = callback->getter() != NULL && | 953 compile_followup_inline = |
956 callback->IsCompatibleReceiver(*object); | 954 callback->getter() != NULL && |
| 955 (!callback->HasExpectedReceiverType() || |
| 956 callback->IsCompatibleReceiver(*IC::TypeToMap(*type(), isolate()))); |
957 } | 957 } |
958 } | 958 } |
959 | 959 |
960 if (compile_followup_inline) { | 960 if (compile_followup_inline) { |
961 // Compile the interceptor call, followed by inline code to load the | 961 // Compile the interceptor call, followed by inline code to load the |
962 // property from further up the prototype chain if the call fails. | 962 // property from further up the prototype chain if the call fails. |
963 // Check that the maps haven't changed. | 963 // Check that the maps haven't changed. |
964 ASSERT(holder_reg.is(receiver()) || holder_reg.is(scratch1())); | 964 ASSERT(holder_reg.is(receiver()) || holder_reg.is(scratch1())); |
965 | 965 |
966 // Preserve the receiver register explicitly whenever it is different from | 966 // Preserve the receiver register explicitly whenever it is different from |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1017 __ TailCallExternalReference( | 1017 __ TailCallExternalReference( |
1018 ref, NamedLoadHandlerCompiler::kInterceptorArgsLength, 1); | 1018 ref, NamedLoadHandlerCompiler::kInterceptorArgsLength, 1); |
1019 } | 1019 } |
1020 } | 1020 } |
1021 | 1021 |
1022 | 1022 |
1023 Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( | 1023 Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( |
1024 Handle<JSObject> object, Handle<JSObject> holder, Handle<Name> name, | 1024 Handle<JSObject> object, Handle<JSObject> holder, Handle<Name> name, |
1025 Handle<ExecutableAccessorInfo> callback) { | 1025 Handle<ExecutableAccessorInfo> callback) { |
1026 ASM_LOCATION("NamedStoreHandlerCompiler::CompileStoreCallback"); | 1026 ASM_LOCATION("NamedStoreHandlerCompiler::CompileStoreCallback"); |
1027 Register holder_reg = | 1027 Register holder_reg = Frontend(receiver(), holder, name); |
1028 Frontend(IC::CurrentTypeOf(object, isolate()), receiver(), holder, name); | |
1029 | 1028 |
1030 // Stub never generated for non-global objects that require access checks. | 1029 // Stub never generated for non-global objects that require access checks. |
1031 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); | 1030 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); |
1032 | 1031 |
1033 // receiver() and holder_reg can alias. | 1032 // receiver() and holder_reg can alias. |
1034 ASSERT(!AreAliased(receiver(), scratch1(), scratch2(), value())); | 1033 ASSERT(!AreAliased(receiver(), scratch1(), scratch2(), value())); |
1035 ASSERT(!AreAliased(holder_reg, scratch1(), scratch2(), value())); | 1034 ASSERT(!AreAliased(holder_reg, scratch1(), scratch2(), value())); |
1036 __ Mov(scratch1(), Operand(callback)); | 1035 __ Mov(scratch1(), Operand(callback)); |
1037 __ Mov(scratch2(), Operand(name)); | 1036 __ Mov(scratch2(), Operand(name)); |
1038 __ Push(receiver(), holder_reg, scratch1(), scratch2(), value()); | 1037 __ Push(receiver(), holder_reg, scratch1(), scratch2(), value()); |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1109 ExternalReference store_ic_property = ExternalReference( | 1108 ExternalReference store_ic_property = ExternalReference( |
1110 IC_Utility(IC::kStorePropertyWithInterceptor), isolate()); | 1109 IC_Utility(IC::kStorePropertyWithInterceptor), isolate()); |
1111 __ TailCallExternalReference(store_ic_property, 3, 1); | 1110 __ TailCallExternalReference(store_ic_property, 3, 1); |
1112 | 1111 |
1113 // Return the generated code. | 1112 // Return the generated code. |
1114 return GetCode(kind(), Code::FAST, name); | 1113 return GetCode(kind(), Code::FAST, name); |
1115 } | 1114 } |
1116 | 1115 |
1117 | 1116 |
1118 Handle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent( | 1117 Handle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent( |
1119 Handle<HeapType> type, Handle<JSObject> last, Handle<Name> name) { | 1118 Handle<JSObject> last, Handle<Name> name) { |
1120 NonexistentFrontend(type, last, name); | 1119 NonexistentFrontend(last, name); |
1121 | 1120 |
1122 // Return undefined if maps of the full prototype chain are still the | 1121 // Return undefined if maps of the full prototype chain are still the |
1123 // same and no global property with this name contains a value. | 1122 // same and no global property with this name contains a value. |
1124 __ LoadRoot(x0, Heap::kUndefinedValueRootIndex); | 1123 __ LoadRoot(x0, Heap::kUndefinedValueRootIndex); |
1125 __ Ret(); | 1124 __ Ret(); |
1126 | 1125 |
1127 // Return the generated code. | 1126 // Return the generated code. |
1128 return GetCode(kind(), Code::FAST, name); | 1127 return GetCode(kind(), Code::FAST, name); |
1129 } | 1128 } |
1130 | 1129 |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1199 } | 1198 } |
1200 __ Ret(); | 1199 __ Ret(); |
1201 } | 1200 } |
1202 | 1201 |
1203 | 1202 |
1204 #undef __ | 1203 #undef __ |
1205 #define __ ACCESS_MASM(masm()) | 1204 #define __ ACCESS_MASM(masm()) |
1206 | 1205 |
1207 | 1206 |
1208 Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( | 1207 Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( |
1209 Handle<HeapType> type, Handle<GlobalObject> global, | 1208 Handle<GlobalObject> global, Handle<PropertyCell> cell, Handle<Name> name, |
1210 Handle<PropertyCell> cell, Handle<Name> name, bool is_dont_delete) { | 1209 bool is_dont_delete) { |
1211 Label miss; | 1210 Label miss; |
1212 FrontendHeader(type, receiver(), global, name, &miss); | 1211 FrontendHeader(receiver(), global, name, &miss); |
1213 | 1212 |
1214 // Get the value from the cell. | 1213 // Get the value from the cell. |
1215 __ Mov(x3, Operand(cell)); | 1214 Register result = StoreIC::ValueRegister(); |
1216 __ Ldr(x4, FieldMemOperand(x3, Cell::kValueOffset)); | 1215 __ Mov(result, Operand(cell)); |
| 1216 __ Ldr(result, FieldMemOperand(result, Cell::kValueOffset)); |
1217 | 1217 |
1218 // Check for deleted property if property can actually be deleted. | 1218 // Check for deleted property if property can actually be deleted. |
1219 if (!is_dont_delete) { | 1219 if (!is_dont_delete) { |
1220 __ JumpIfRoot(x4, Heap::kTheHoleValueRootIndex, &miss); | 1220 __ JumpIfRoot(result, Heap::kTheHoleValueRootIndex, &miss); |
1221 } | 1221 } |
1222 | 1222 |
1223 Counters* counters = isolate()->counters(); | 1223 Counters* counters = isolate()->counters(); |
1224 __ IncrementCounter(counters->named_load_global_stub(), 1, x1, x3); | 1224 __ IncrementCounter(counters->named_load_global_stub(), 1, x1, x3); |
1225 __ Mov(x0, x4); | |
1226 __ Ret(); | 1225 __ Ret(); |
1227 | 1226 |
1228 FrontendFooter(name, &miss); | 1227 FrontendFooter(name, &miss); |
1229 | 1228 |
1230 // Return the generated code. | 1229 // Return the generated code. |
1231 return GetCode(kind(), Code::NORMAL, name); | 1230 return GetCode(kind(), Code::NORMAL, name); |
1232 } | 1231 } |
1233 | 1232 |
1234 | 1233 |
1235 Handle<Code> PropertyICCompiler::CompilePolymorphic(TypeHandleList* types, | 1234 Handle<Code> PropertyICCompiler::CompilePolymorphic(TypeHandleList* types, |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1352 | 1351 |
1353 // Miss case, call the runtime. | 1352 // Miss case, call the runtime. |
1354 __ Bind(&miss); | 1353 __ Bind(&miss); |
1355 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); | 1354 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); |
1356 } | 1355 } |
1357 | 1356 |
1358 | 1357 |
1359 } } // namespace v8::internal | 1358 } } // namespace v8::internal |
1360 | 1359 |
1361 #endif // V8_TARGET_ARCH_ARM64 | 1360 #endif // V8_TARGET_ARCH_ARM64 |
OLD | NEW |