| 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 |