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_ARM | 7 #if V8_TARGET_ARCH_ARM |
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 715 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
726 Handle<Code> code) { | 726 Handle<Code> code) { |
727 __ Jump(code, RelocInfo::CODE_TARGET); | 727 __ Jump(code, RelocInfo::CODE_TARGET); |
728 } | 728 } |
729 | 729 |
730 | 730 |
731 #undef __ | 731 #undef __ |
732 #define __ ACCESS_MASM(masm()) | 732 #define __ ACCESS_MASM(masm()) |
733 | 733 |
734 | 734 |
735 Register PropertyHandlerCompiler::CheckPrototypes( | 735 Register PropertyHandlerCompiler::CheckPrototypes( |
736 Handle<HeapType> type, Register object_reg, Handle<JSObject> holder, | 736 Register object_reg, Handle<JSObject> holder, Register holder_reg, |
737 Register holder_reg, Register scratch1, Register scratch2, | 737 Register scratch1, Register scratch2, Handle<Name> name, Label* miss, |
738 Handle<Name> name, Label* miss, PrototypeCheckType check) { | 738 PrototypeCheckType check) { |
739 Handle<Map> receiver_map(IC::TypeToMap(*type, isolate())); | 739 Handle<Map> receiver_map(IC::TypeToMap(*type(), isolate())); |
740 | 740 |
741 // Make sure there's no overlap between holder and object registers. | 741 // Make sure there's no overlap between holder and object registers. |
742 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); | 742 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); |
743 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) | 743 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) |
744 && !scratch2.is(scratch1)); | 744 && !scratch2.is(scratch1)); |
745 | 745 |
746 // Keep track of the current object in register reg. | 746 // Keep track of the current object in register reg. |
747 Register reg = object_reg; | 747 Register reg = object_reg; |
748 int depth = 0; | 748 int depth = 0; |
749 | 749 |
750 Handle<JSObject> current = Handle<JSObject>::null(); | 750 Handle<JSObject> current = Handle<JSObject>::null(); |
751 if (type->IsConstant()) { | 751 if (type()->IsConstant()) { |
752 current = Handle<JSObject>::cast(type->AsConstant()->Value()); | 752 current = Handle<JSObject>::cast(type()->AsConstant()->Value()); |
753 } | 753 } |
754 Handle<JSObject> prototype = Handle<JSObject>::null(); | 754 Handle<JSObject> prototype = Handle<JSObject>::null(); |
755 Handle<Map> current_map = receiver_map; | 755 Handle<Map> current_map = receiver_map; |
756 Handle<Map> holder_map(holder->map()); | 756 Handle<Map> holder_map(holder->map()); |
757 // Traverse the prototype chain and check the maps in the prototype chain for | 757 // Traverse the prototype chain and check the maps in the prototype chain for |
758 // fast and global objects or do negative lookup for normal objects. | 758 // fast and global objects or do negative lookup for normal objects. |
759 while (!current_map.is_identical_to(holder_map)) { | 759 while (!current_map.is_identical_to(holder_map)) { |
760 ++depth; | 760 ++depth; |
761 | 761 |
762 // Only global objects and objects that do not require access | 762 // Only global objects and objects that do not require access |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
857 if (!miss->is_unused()) { | 857 if (!miss->is_unused()) { |
858 Label success; | 858 Label success; |
859 __ b(&success); | 859 __ b(&success); |
860 GenerateRestoreName(masm(), miss, name); | 860 GenerateRestoreName(masm(), miss, name); |
861 TailCallBuiltin(masm(), MissBuiltin(kind())); | 861 TailCallBuiltin(masm(), MissBuiltin(kind())); |
862 __ bind(&success); | 862 __ bind(&success); |
863 } | 863 } |
864 } | 864 } |
865 | 865 |
866 | 866 |
867 Register NamedLoadHandlerCompiler::CallbackFrontend(Handle<HeapType> type, | 867 Register NamedLoadHandlerCompiler::CallbackFrontend(Register object_reg, |
868 Register object_reg, | |
869 Handle<JSObject> holder, | 868 Handle<JSObject> holder, |
870 Handle<Name> name, | 869 Handle<Name> name, |
871 Handle<Object> callback) { | 870 Handle<Object> callback) { |
872 Label miss; | 871 Label miss; |
873 | 872 |
874 Register reg = FrontendHeader(type, object_reg, holder, name, &miss); | 873 Register reg = FrontendHeader(object_reg, holder, name, &miss); |
875 | 874 |
876 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { | 875 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { |
877 ASSERT(!reg.is(scratch2())); | 876 ASSERT(!reg.is(scratch2())); |
878 ASSERT(!reg.is(scratch3())); | 877 ASSERT(!reg.is(scratch3())); |
879 ASSERT(!reg.is(scratch4())); | 878 ASSERT(!reg.is(scratch4())); |
880 | 879 |
881 // Load the properties dictionary. | 880 // Load the properties dictionary. |
882 Register dictionary = scratch4(); | 881 Register dictionary = scratch4(); |
883 __ ldr(dictionary, FieldMemOperand(reg, JSObject::kPropertiesOffset)); | 882 __ ldr(dictionary, FieldMemOperand(reg, JSObject::kPropertiesOffset)); |
884 | 883 |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
965 ExternalReference::Type type = ExternalReference::DIRECT_GETTER_CALL; | 964 ExternalReference::Type type = ExternalReference::DIRECT_GETTER_CALL; |
966 ExternalReference ref = ExternalReference(&fun, type, isolate()); | 965 ExternalReference ref = ExternalReference(&fun, type, isolate()); |
967 __ mov(getter_address_reg, Operand(ref)); | 966 __ mov(getter_address_reg, Operand(ref)); |
968 | 967 |
969 CallApiGetterStub stub(isolate()); | 968 CallApiGetterStub stub(isolate()); |
970 __ TailCallStub(&stub); | 969 __ TailCallStub(&stub); |
971 } | 970 } |
972 | 971 |
973 | 972 |
974 void NamedLoadHandlerCompiler::GenerateLoadInterceptor( | 973 void NamedLoadHandlerCompiler::GenerateLoadInterceptor( |
975 Register holder_reg, Handle<Object> object, | 974 Register holder_reg, Handle<JSObject> interceptor_holder, |
976 Handle<JSObject> interceptor_holder, LookupResult* lookup, | 975 LookupResult* lookup, Handle<Name> name) { |
977 Handle<Name> name) { | |
978 ASSERT(interceptor_holder->HasNamedInterceptor()); | 976 ASSERT(interceptor_holder->HasNamedInterceptor()); |
979 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); | 977 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); |
980 | 978 |
981 // So far the most popular follow ups for interceptor loads are FIELD | 979 // So far the most popular follow ups for interceptor loads are FIELD |
982 // and CALLBACKS, so inline only them, other cases may be added | 980 // and CALLBACKS, so inline only them, other cases may be added |
983 // later. | 981 // later. |
984 bool compile_followup_inline = false; | 982 bool compile_followup_inline = false; |
985 if (lookup->IsFound() && lookup->IsCacheable()) { | 983 if (lookup->IsFound() && lookup->IsCacheable()) { |
986 if (lookup->IsField()) { | 984 if (lookup->IsField()) { |
987 compile_followup_inline = true; | 985 compile_followup_inline = true; |
988 } else if (lookup->type() == CALLBACKS && | 986 } else if (lookup->type() == CALLBACKS && |
989 lookup->GetCallbackObject()->IsExecutableAccessorInfo()) { | 987 lookup->GetCallbackObject()->IsExecutableAccessorInfo()) { |
990 ExecutableAccessorInfo* callback = | 988 ExecutableAccessorInfo* callback = |
991 ExecutableAccessorInfo::cast(lookup->GetCallbackObject()); | 989 ExecutableAccessorInfo::cast(lookup->GetCallbackObject()); |
992 compile_followup_inline = callback->getter() != NULL && | 990 compile_followup_inline = |
993 callback->IsCompatibleReceiver(*object); | 991 callback->getter() != NULL && |
| 992 (!callback->HasExpectedReceiverType() || |
| 993 callback->IsCompatibleReceiver(*IC::TypeToMap(*type(), isolate()))); |
994 } | 994 } |
995 } | 995 } |
996 | 996 |
997 if (compile_followup_inline) { | 997 if (compile_followup_inline) { |
998 // Compile the interceptor call, followed by inline code to load the | 998 // Compile the interceptor call, followed by inline code to load the |
999 // property from further up the prototype chain if the call fails. | 999 // property from further up the prototype chain if the call fails. |
1000 // Check that the maps haven't changed. | 1000 // Check that the maps haven't changed. |
1001 ASSERT(holder_reg.is(receiver()) || holder_reg.is(scratch1())); | 1001 ASSERT(holder_reg.is(receiver()) || holder_reg.is(scratch1())); |
1002 | 1002 |
1003 // Preserve the receiver register explicitly whenever it is different from | 1003 // Preserve the receiver register explicitly whenever it is different from |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1054 isolate()); | 1054 isolate()); |
1055 __ TailCallExternalReference( | 1055 __ TailCallExternalReference( |
1056 ref, NamedLoadHandlerCompiler::kInterceptorArgsLength, 1); | 1056 ref, NamedLoadHandlerCompiler::kInterceptorArgsLength, 1); |
1057 } | 1057 } |
1058 } | 1058 } |
1059 | 1059 |
1060 | 1060 |
1061 Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( | 1061 Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( |
1062 Handle<JSObject> object, Handle<JSObject> holder, Handle<Name> name, | 1062 Handle<JSObject> object, Handle<JSObject> holder, Handle<Name> name, |
1063 Handle<ExecutableAccessorInfo> callback) { | 1063 Handle<ExecutableAccessorInfo> callback) { |
1064 Register holder_reg = | 1064 Register holder_reg = Frontend(receiver(), holder, name); |
1065 Frontend(IC::CurrentTypeOf(object, isolate()), receiver(), holder, name); | |
1066 | 1065 |
1067 // Stub never generated for non-global objects that require access checks. | 1066 // Stub never generated for non-global objects that require access checks. |
1068 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); | 1067 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); |
1069 | 1068 |
1070 __ push(receiver()); // receiver | 1069 __ push(receiver()); // receiver |
1071 __ push(holder_reg); | 1070 __ push(holder_reg); |
1072 __ mov(ip, Operand(callback)); // callback info | 1071 __ mov(ip, Operand(callback)); // callback info |
1073 __ push(ip); | 1072 __ push(ip); |
1074 __ mov(ip, Operand(name)); | 1073 __ mov(ip, Operand(name)); |
1075 __ Push(ip, value()); | 1074 __ Push(ip, value()); |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1140 ExternalReference store_ic_property = ExternalReference( | 1139 ExternalReference store_ic_property = ExternalReference( |
1141 IC_Utility(IC::kStorePropertyWithInterceptor), isolate()); | 1140 IC_Utility(IC::kStorePropertyWithInterceptor), isolate()); |
1142 __ TailCallExternalReference(store_ic_property, 3, 1); | 1141 __ TailCallExternalReference(store_ic_property, 3, 1); |
1143 | 1142 |
1144 // Return the generated code. | 1143 // Return the generated code. |
1145 return GetCode(kind(), Code::FAST, name); | 1144 return GetCode(kind(), Code::FAST, name); |
1146 } | 1145 } |
1147 | 1146 |
1148 | 1147 |
1149 Handle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent( | 1148 Handle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent( |
1150 Handle<HeapType> type, Handle<JSObject> last, Handle<Name> name) { | 1149 Handle<JSObject> last, Handle<Name> name) { |
1151 NonexistentFrontend(type, last, name); | 1150 NonexistentFrontend(last, name); |
1152 | 1151 |
1153 // Return undefined if maps of the full prototype chain are still the | 1152 // Return undefined if maps of the full prototype chain are still the |
1154 // same and no global property with this name contains a value. | 1153 // same and no global property with this name contains a value. |
1155 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); | 1154 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); |
1156 __ Ret(); | 1155 __ Ret(); |
1157 | 1156 |
1158 // Return the generated code. | 1157 // Return the generated code. |
1159 return GetCode(kind(), Code::FAST, name); | 1158 return GetCode(kind(), Code::FAST, name); |
1160 } | 1159 } |
1161 | 1160 |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1229 } | 1228 } |
1230 __ Ret(); | 1229 __ Ret(); |
1231 } | 1230 } |
1232 | 1231 |
1233 | 1232 |
1234 #undef __ | 1233 #undef __ |
1235 #define __ ACCESS_MASM(masm()) | 1234 #define __ ACCESS_MASM(masm()) |
1236 | 1235 |
1237 | 1236 |
1238 Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( | 1237 Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( |
1239 Handle<HeapType> type, Handle<GlobalObject> global, | 1238 Handle<GlobalObject> global, Handle<PropertyCell> cell, Handle<Name> name, |
1240 Handle<PropertyCell> cell, Handle<Name> name, bool is_dont_delete) { | 1239 bool is_dont_delete) { |
1241 Label miss; | 1240 Label miss; |
1242 FrontendHeader(type, receiver(), global, name, &miss); | 1241 FrontendHeader(receiver(), global, name, &miss); |
1243 | 1242 |
1244 // Get the value from the cell. | 1243 // Get the value from the cell. |
1245 __ mov(r3, Operand(cell)); | 1244 Register result = StoreIC::ValueRegister(); |
1246 __ ldr(r4, FieldMemOperand(r3, Cell::kValueOffset)); | 1245 __ mov(result, Operand(cell)); |
| 1246 __ ldr(result, FieldMemOperand(result, Cell::kValueOffset)); |
1247 | 1247 |
1248 // Check for deleted property if property can actually be deleted. | 1248 // Check for deleted property if property can actually be deleted. |
1249 if (!is_dont_delete) { | 1249 if (!is_dont_delete) { |
1250 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); | 1250 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); |
1251 __ cmp(r4, ip); | 1251 __ cmp(result, ip); |
1252 __ b(eq, &miss); | 1252 __ b(eq, &miss); |
1253 } | 1253 } |
1254 | 1254 |
1255 Counters* counters = isolate()->counters(); | 1255 Counters* counters = isolate()->counters(); |
1256 __ IncrementCounter(counters->named_load_global_stub(), 1, r1, r3); | 1256 __ IncrementCounter(counters->named_load_global_stub(), 1, r1, r3); |
1257 __ mov(r0, r4); | |
1258 __ Ret(); | 1257 __ Ret(); |
1259 | 1258 |
1260 FrontendFooter(name, &miss); | 1259 FrontendFooter(name, &miss); |
1261 | 1260 |
1262 // Return the generated code. | 1261 // Return the generated code. |
1263 return GetCode(kind(), Code::NORMAL, name); | 1262 return GetCode(kind(), Code::NORMAL, name); |
1264 } | 1263 } |
1265 | 1264 |
1266 | 1265 |
1267 Handle<Code> PropertyICCompiler::CompilePolymorphic(TypeHandleList* types, | 1266 Handle<Code> PropertyICCompiler::CompilePolymorphic(TypeHandleList* types, |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1387 | 1386 |
1388 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); | 1387 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); |
1389 } | 1388 } |
1390 | 1389 |
1391 | 1390 |
1392 #undef __ | 1391 #undef __ |
1393 | 1392 |
1394 } } // namespace v8::internal | 1393 } } // namespace v8::internal |
1395 | 1394 |
1396 #endif // V8_TARGET_ARCH_ARM | 1395 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |