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