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 674 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
685 Handle<Code> code) { | 685 Handle<Code> code) { |
686 __ jmp(code, RelocInfo::CODE_TARGET); | 686 __ jmp(code, RelocInfo::CODE_TARGET); |
687 } | 687 } |
688 | 688 |
689 | 689 |
690 #undef __ | 690 #undef __ |
691 #define __ ACCESS_MASM(masm()) | 691 #define __ ACCESS_MASM(masm()) |
692 | 692 |
693 | 693 |
694 Register PropertyHandlerCompiler::CheckPrototypes( | 694 Register PropertyHandlerCompiler::CheckPrototypes( |
695 Handle<HeapType> type, Register object_reg, Handle<JSObject> holder, | 695 Register object_reg, Handle<JSObject> holder, Register holder_reg, |
696 Register holder_reg, Register scratch1, Register scratch2, | 696 Register scratch1, Register scratch2, Handle<Name> name, Label* miss, |
697 Handle<Name> name, Label* miss, PrototypeCheckType check) { | 697 PrototypeCheckType check) { |
698 Handle<Map> receiver_map(IC::TypeToMap(*type, isolate())); | 698 Handle<Map> receiver_map(IC::TypeToMap(*type(), isolate())); |
699 | 699 |
700 // Make sure there's no overlap between holder and object registers. | 700 // Make sure there's no overlap between holder and object registers. |
701 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); | 701 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); |
702 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) | 702 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) |
703 && !scratch2.is(scratch1)); | 703 && !scratch2.is(scratch1)); |
704 | 704 |
705 // Keep track of the current object in register reg. | 705 // Keep track of the current object in register reg. |
706 Register reg = object_reg; | 706 Register reg = object_reg; |
707 int depth = 0; | 707 int depth = 0; |
708 | 708 |
709 Handle<JSObject> current = Handle<JSObject>::null(); | 709 Handle<JSObject> current = Handle<JSObject>::null(); |
710 if (type->IsConstant()) current = | 710 if (type()->IsConstant()) |
711 Handle<JSObject>::cast(type->AsConstant()->Value()); | 711 current = Handle<JSObject>::cast(type()->AsConstant()->Value()); |
712 Handle<JSObject> prototype = Handle<JSObject>::null(); | 712 Handle<JSObject> prototype = Handle<JSObject>::null(); |
713 Handle<Map> current_map = receiver_map; | 713 Handle<Map> current_map = receiver_map; |
714 Handle<Map> holder_map(holder->map()); | 714 Handle<Map> holder_map(holder->map()); |
715 // Traverse the prototype chain and check the maps in the prototype chain for | 715 // 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. | 716 // fast and global objects or do negative lookup for normal objects. |
717 while (!current_map.is_identical_to(holder_map)) { | 717 while (!current_map.is_identical_to(holder_map)) { |
718 ++depth; | 718 ++depth; |
719 | 719 |
720 // Only global objects and objects that do not require access | 720 // Only global objects and objects that do not require access |
721 // checks are allowed in stubs. | 721 // checks are allowed in stubs. |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
816 if (!miss->is_unused()) { | 816 if (!miss->is_unused()) { |
817 Label success; | 817 Label success; |
818 __ jmp(&success); | 818 __ jmp(&success); |
819 GenerateRestoreName(masm(), miss, name); | 819 GenerateRestoreName(masm(), miss, name); |
820 TailCallBuiltin(masm(), MissBuiltin(kind())); | 820 TailCallBuiltin(masm(), MissBuiltin(kind())); |
821 __ bind(&success); | 821 __ bind(&success); |
822 } | 822 } |
823 } | 823 } |
824 | 824 |
825 | 825 |
826 Register NamedLoadHandlerCompiler::CallbackFrontend(Handle<HeapType> type, | 826 Register NamedLoadHandlerCompiler::CallbackFrontend(Register object_reg, |
827 Register object_reg, | |
828 Handle<JSObject> holder, | 827 Handle<JSObject> holder, |
829 Handle<Name> name, | 828 Handle<Name> name, |
830 Handle<Object> callback) { | 829 Handle<Object> callback) { |
831 Label miss; | 830 Label miss; |
832 | 831 |
833 Register reg = FrontendHeader(type, object_reg, holder, name, &miss); | 832 Register reg = FrontendHeader(object_reg, holder, name, &miss); |
834 | 833 |
835 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { | 834 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { |
836 ASSERT(!reg.is(scratch2())); | 835 ASSERT(!reg.is(scratch2())); |
837 ASSERT(!reg.is(scratch3())); | 836 ASSERT(!reg.is(scratch3())); |
838 Register dictionary = scratch1(); | 837 Register dictionary = scratch1(); |
839 bool must_preserve_dictionary_reg = reg.is(dictionary); | 838 bool must_preserve_dictionary_reg = reg.is(dictionary); |
840 | 839 |
841 // Load the properties dictionary. | 840 // Load the properties dictionary. |
842 if (must_preserve_dictionary_reg) { | 841 if (must_preserve_dictionary_reg) { |
843 __ push(dictionary); | 842 __ push(dictionary); |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
936 | 935 |
937 | 936 |
938 void NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) { | 937 void NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) { |
939 // Return the constant value. | 938 // Return the constant value. |
940 __ LoadObject(eax, value); | 939 __ LoadObject(eax, value); |
941 __ ret(0); | 940 __ ret(0); |
942 } | 941 } |
943 | 942 |
944 | 943 |
945 void NamedLoadHandlerCompiler::GenerateLoadInterceptor( | 944 void NamedLoadHandlerCompiler::GenerateLoadInterceptor( |
946 Register holder_reg, Handle<Object> object, | 945 Register holder_reg, Handle<JSObject> interceptor_holder, |
947 Handle<JSObject> interceptor_holder, LookupResult* lookup, | 946 LookupResult* lookup, Handle<Name> name) { |
948 Handle<Name> name) { | |
949 ASSERT(interceptor_holder->HasNamedInterceptor()); | 947 ASSERT(interceptor_holder->HasNamedInterceptor()); |
950 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); | 948 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); |
951 | 949 |
952 // So far the most popular follow ups for interceptor loads are FIELD | 950 // So far the most popular follow ups for interceptor loads are FIELD |
953 // and CALLBACKS, so inline only them, other cases may be added | 951 // and CALLBACKS, so inline only them, other cases may be added |
954 // later. | 952 // later. |
955 bool compile_followup_inline = false; | 953 bool compile_followup_inline = false; |
956 if (lookup->IsFound() && lookup->IsCacheable()) { | 954 if (lookup->IsFound() && lookup->IsCacheable()) { |
957 if (lookup->IsField()) { | 955 if (lookup->IsField()) { |
958 compile_followup_inline = true; | 956 compile_followup_inline = true; |
959 } else if (lookup->type() == CALLBACKS && | 957 } else if (lookup->type() == CALLBACKS && |
960 lookup->GetCallbackObject()->IsExecutableAccessorInfo()) { | 958 lookup->GetCallbackObject()->IsExecutableAccessorInfo()) { |
961 ExecutableAccessorInfo* callback = | 959 Handle<ExecutableAccessorInfo> callback( |
962 ExecutableAccessorInfo::cast(lookup->GetCallbackObject()); | 960 ExecutableAccessorInfo::cast(lookup->GetCallbackObject())); |
963 compile_followup_inline = callback->getter() != NULL && | 961 compile_followup_inline = |
964 callback->IsCompatibleReceiver(*object); | 962 callback->getter() != NULL && |
| 963 ExecutableAccessorInfo::IsCompatibleReceiverType(isolate(), callback, |
| 964 type()); |
965 } | 965 } |
966 } | 966 } |
967 | 967 |
968 if (compile_followup_inline) { | 968 if (compile_followup_inline) { |
969 // Compile the interceptor call, followed by inline code to load the | 969 // Compile the interceptor call, followed by inline code to load the |
970 // property from further up the prototype chain if the call fails. | 970 // property from further up the prototype chain if the call fails. |
971 // Check that the maps haven't changed. | 971 // Check that the maps haven't changed. |
972 ASSERT(holder_reg.is(receiver()) || holder_reg.is(scratch1())); | 972 ASSERT(holder_reg.is(receiver()) || holder_reg.is(scratch1())); |
973 | 973 |
974 // Preserve the receiver register explicitly whenever it is different from | 974 // Preserve the receiver register explicitly whenever it is different from |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1036 isolate()); | 1036 isolate()); |
1037 __ TailCallExternalReference( | 1037 __ TailCallExternalReference( |
1038 ref, NamedLoadHandlerCompiler::kInterceptorArgsLength, 1); | 1038 ref, NamedLoadHandlerCompiler::kInterceptorArgsLength, 1); |
1039 } | 1039 } |
1040 } | 1040 } |
1041 | 1041 |
1042 | 1042 |
1043 Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( | 1043 Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( |
1044 Handle<JSObject> object, Handle<JSObject> holder, Handle<Name> name, | 1044 Handle<JSObject> object, Handle<JSObject> holder, Handle<Name> name, |
1045 Handle<ExecutableAccessorInfo> callback) { | 1045 Handle<ExecutableAccessorInfo> callback) { |
1046 Register holder_reg = | 1046 Register holder_reg = Frontend(receiver(), holder, name); |
1047 Frontend(IC::CurrentTypeOf(object, isolate()), receiver(), holder, name); | |
1048 | 1047 |
1049 __ pop(scratch1()); // remove the return address | 1048 __ pop(scratch1()); // remove the return address |
1050 __ push(receiver()); | 1049 __ push(receiver()); |
1051 __ push(holder_reg); | 1050 __ push(holder_reg); |
1052 __ Push(callback); | 1051 __ Push(callback); |
1053 __ Push(name); | 1052 __ Push(name); |
1054 __ push(value()); | 1053 __ push(value()); |
1055 __ push(scratch1()); // restore return address | 1054 __ push(scratch1()); // restore return address |
1056 | 1055 |
1057 // Do tail-call to the runtime system. | 1056 // Do tail-call to the runtime system. |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1165 } | 1164 } |
1166 __ bind(&miss); | 1165 __ bind(&miss); |
1167 TailCallBuiltin(masm(), MissBuiltin(kind())); | 1166 TailCallBuiltin(masm(), MissBuiltin(kind())); |
1168 | 1167 |
1169 // Return the generated code. | 1168 // Return the generated code. |
1170 return GetCode(kind(), Code::NORMAL, factory()->empty_string(), POLYMORPHIC); | 1169 return GetCode(kind(), Code::NORMAL, factory()->empty_string(), POLYMORPHIC); |
1171 } | 1170 } |
1172 | 1171 |
1173 | 1172 |
1174 Handle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent( | 1173 Handle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent( |
1175 Handle<HeapType> type, Handle<JSObject> last, Handle<Name> name) { | 1174 Handle<JSObject> last, Handle<Name> name) { |
1176 NonexistentFrontend(type, last, name); | 1175 NonexistentFrontend(last, name); |
1177 | 1176 |
1178 // Return undefined if maps of the full prototype chain are still the | 1177 // Return undefined if maps of the full prototype chain are still the |
1179 // same and no global property with this name contains a value. | 1178 // same and no global property with this name contains a value. |
1180 __ mov(eax, isolate()->factory()->undefined_value()); | 1179 __ mov(eax, isolate()->factory()->undefined_value()); |
1181 __ ret(0); | 1180 __ ret(0); |
1182 | 1181 |
1183 // Return the generated code. | 1182 // Return the generated code. |
1184 return GetCode(kind(), Code::FAST, name); | 1183 return GetCode(kind(), Code::FAST, name); |
1185 } | 1184 } |
1186 | 1185 |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1249 } | 1248 } |
1250 __ ret(0); | 1249 __ ret(0); |
1251 } | 1250 } |
1252 | 1251 |
1253 | 1252 |
1254 #undef __ | 1253 #undef __ |
1255 #define __ ACCESS_MASM(masm()) | 1254 #define __ ACCESS_MASM(masm()) |
1256 | 1255 |
1257 | 1256 |
1258 Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( | 1257 Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( |
1259 Handle<HeapType> type, Handle<GlobalObject> global, | 1258 Handle<GlobalObject> global, Handle<PropertyCell> cell, Handle<Name> name, |
1260 Handle<PropertyCell> cell, Handle<Name> name, bool is_dont_delete) { | 1259 bool is_dont_delete) { |
1261 Label miss; | 1260 Label miss; |
1262 | 1261 |
1263 FrontendHeader(type, receiver(), global, name, &miss); | 1262 FrontendHeader(receiver(), global, name, &miss); |
1264 // Get the value from the cell. | 1263 // Get the value from the cell. |
| 1264 Register result = StoreIC::ValueRegister(); |
1265 if (masm()->serializer_enabled()) { | 1265 if (masm()->serializer_enabled()) { |
1266 __ mov(eax, Immediate(cell)); | 1266 __ mov(result, Immediate(cell)); |
1267 __ mov(eax, FieldOperand(eax, PropertyCell::kValueOffset)); | 1267 __ mov(result, FieldOperand(result, PropertyCell::kValueOffset)); |
1268 } else { | 1268 } else { |
1269 __ mov(eax, Operand::ForCell(cell)); | 1269 __ mov(result, Operand::ForCell(cell)); |
1270 } | 1270 } |
1271 | 1271 |
1272 // Check for deleted property if property can actually be deleted. | 1272 // Check for deleted property if property can actually be deleted. |
1273 if (!is_dont_delete) { | 1273 if (!is_dont_delete) { |
1274 __ cmp(eax, factory()->the_hole_value()); | 1274 __ cmp(result, factory()->the_hole_value()); |
1275 __ j(equal, &miss); | 1275 __ j(equal, &miss); |
1276 } else if (FLAG_debug_code) { | 1276 } else if (FLAG_debug_code) { |
1277 __ cmp(eax, factory()->the_hole_value()); | 1277 __ cmp(result, factory()->the_hole_value()); |
1278 __ Check(not_equal, kDontDeleteCellsCannotContainTheHole); | 1278 __ Check(not_equal, kDontDeleteCellsCannotContainTheHole); |
1279 } | 1279 } |
1280 | 1280 |
1281 Counters* counters = isolate()->counters(); | 1281 Counters* counters = isolate()->counters(); |
1282 __ IncrementCounter(counters->named_load_global_stub(), 1); | 1282 __ IncrementCounter(counters->named_load_global_stub(), 1); |
1283 // The code above already loads the result into the return register. | 1283 // The code above already loads the result into the return register. |
1284 __ ret(0); | 1284 __ ret(0); |
1285 | 1285 |
1286 FrontendFooter(name, &miss); | 1286 FrontendFooter(name, &miss); |
1287 | 1287 |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1393 // ----------------------------------- | 1393 // ----------------------------------- |
1394 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); | 1394 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); |
1395 } | 1395 } |
1396 | 1396 |
1397 | 1397 |
1398 #undef __ | 1398 #undef __ |
1399 | 1399 |
1400 } } // namespace v8::internal | 1400 } } // namespace v8::internal |
1401 | 1401 |
1402 #endif // V8_TARGET_ARCH_X87 | 1402 #endif // V8_TARGET_ARCH_X87 |
OLD | NEW |