| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 761 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 772 __ j(not_equal, interceptor_succeeded); | 772 __ j(not_equal, interceptor_succeeded); |
| 773 } | 773 } |
| 774 | 774 |
| 775 StubCompiler* stub_compiler_; | 775 StubCompiler* stub_compiler_; |
| 776 const ParameterCount& arguments_; | 776 const ParameterCount& arguments_; |
| 777 Register name_; | 777 Register name_; |
| 778 Code::ExtraICState extra_state_; | 778 Code::ExtraICState extra_state_; |
| 779 }; | 779 }; |
| 780 | 780 |
| 781 | 781 |
| 782 void BaseStoreStubCompiler::GenerateRestoreName(MacroAssembler* masm, | 782 void StoreStubCompiler::GenerateRestoreName(MacroAssembler* masm, |
| 783 Label* label, | 783 Label* label, |
| 784 Handle<Name> name) { | 784 Handle<Name> name) { |
| 785 if (!label->is_unused()) { | 785 if (!label->is_unused()) { |
| 786 __ bind(label); | 786 __ bind(label); |
| 787 __ mov(this->name(), Immediate(name)); | 787 __ mov(this->name(), Immediate(name)); |
| 788 } | 788 } |
| 789 } | 789 } |
| 790 | 790 |
| 791 | 791 |
| 792 // Generate code to check that a global property cell is empty. Create | 792 // Generate code to check that a global property cell is empty. Create |
| 793 // the property cell at compilation time if no cell exists for the | 793 // the property cell at compilation time if no cell exists for the |
| 794 // property. | 794 // property. |
| (...skipping 10 matching lines...) Expand all Loading... |
| 805 __ mov(scratch, Immediate(cell)); | 805 __ mov(scratch, Immediate(cell)); |
| 806 __ cmp(FieldOperand(scratch, PropertyCell::kValueOffset), | 806 __ cmp(FieldOperand(scratch, PropertyCell::kValueOffset), |
| 807 Immediate(the_hole)); | 807 Immediate(the_hole)); |
| 808 } else { | 808 } else { |
| 809 __ cmp(Operand::ForCell(cell), Immediate(the_hole)); | 809 __ cmp(Operand::ForCell(cell), Immediate(the_hole)); |
| 810 } | 810 } |
| 811 __ j(not_equal, miss); | 811 __ j(not_equal, miss); |
| 812 } | 812 } |
| 813 | 813 |
| 814 | 814 |
| 815 void BaseStoreStubCompiler::GenerateNegativeHolderLookup( | 815 void StoreStubCompiler::GenerateNegativeHolderLookup( |
| 816 MacroAssembler* masm, | 816 MacroAssembler* masm, |
| 817 Handle<JSObject> holder, | 817 Handle<JSObject> holder, |
| 818 Register holder_reg, | 818 Register holder_reg, |
| 819 Handle<Name> name, | 819 Handle<Name> name, |
| 820 Label* miss) { | 820 Label* miss) { |
| 821 if (holder->IsJSGlobalObject()) { | 821 if (holder->IsJSGlobalObject()) { |
| 822 GenerateCheckPropertyCell( | 822 GenerateCheckPropertyCell( |
| 823 masm, Handle<GlobalObject>::cast(holder), name, scratch1(), miss); | 823 masm, Handle<GlobalObject>::cast(holder), name, scratch1(), miss); |
| 824 } else if (!holder->HasFastProperties() && !holder->IsJSGlobalProxy()) { | 824 } else if (!holder->HasFastProperties() && !holder->IsJSGlobalProxy()) { |
| 825 GenerateDictionaryNegativeLookup( | 825 GenerateDictionaryNegativeLookup( |
| 826 masm, miss, holder_reg, name, scratch1(), scratch2()); | 826 masm, miss, holder_reg, name, scratch1(), scratch2()); |
| 827 } | 827 } |
| 828 } | 828 } |
| 829 | 829 |
| 830 | 830 |
| 831 // Receiver_reg is preserved on jumps to miss_label, but may be destroyed if | 831 // Receiver_reg is preserved on jumps to miss_label, but may be destroyed if |
| 832 // store is successful. | 832 // store is successful. |
| 833 void BaseStoreStubCompiler::GenerateStoreTransition(MacroAssembler* masm, | 833 void StoreStubCompiler::GenerateStoreTransition(MacroAssembler* masm, |
| 834 Handle<JSObject> object, | 834 Handle<JSObject> object, |
| 835 LookupResult* lookup, | 835 LookupResult* lookup, |
| 836 Handle<Map> transition, | 836 Handle<Map> transition, |
| 837 Handle<Name> name, | 837 Handle<Name> name, |
| 838 Register receiver_reg, | 838 Register receiver_reg, |
| 839 Register storage_reg, | 839 Register storage_reg, |
| 840 Register value_reg, | 840 Register value_reg, |
| 841 Register scratch1, | 841 Register scratch1, |
| 842 Register scratch2, | 842 Register scratch2, |
| 843 Register unused, | 843 Register unused, |
| 844 Label* miss_label, | 844 Label* miss_label, |
| 845 Label* slow) { | 845 Label* slow) { |
| 846 int descriptor = transition->LastAdded(); | 846 int descriptor = transition->LastAdded(); |
| 847 DescriptorArray* descriptors = transition->instance_descriptors(); | 847 DescriptorArray* descriptors = transition->instance_descriptors(); |
| 848 PropertyDetails details = descriptors->GetDetails(descriptor); | 848 PropertyDetails details = descriptors->GetDetails(descriptor); |
| 849 Representation representation = details.representation(); | 849 Representation representation = details.representation(); |
| 850 ASSERT(!representation.IsNone()); | 850 ASSERT(!representation.IsNone()); |
| 851 | 851 |
| 852 if (details.type() == CONSTANT) { | 852 if (details.type() == CONSTANT) { |
| 853 Handle<Object> constant(descriptors->GetValue(descriptor), masm->isolate()); | 853 Handle<Object> constant(descriptors->GetValue(descriptor), masm->isolate()); |
| 854 __ CmpObject(value_reg, constant); | 854 __ CmpObject(value_reg, constant); |
| 855 __ j(not_equal, miss_label); | 855 __ j(not_equal, miss_label); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 872 __ pop(value_reg); | 872 __ pop(value_reg); |
| 873 } | 873 } |
| 874 __ SmiTag(value_reg); | 874 __ SmiTag(value_reg); |
| 875 __ jmp(&do_store); | 875 __ jmp(&do_store); |
| 876 | 876 |
| 877 __ bind(&heap_number); | 877 __ bind(&heap_number); |
| 878 __ CheckMap(value_reg, masm->isolate()->factory()->heap_number_map(), | 878 __ CheckMap(value_reg, masm->isolate()->factory()->heap_number_map(), |
| 879 miss_label, DONT_DO_SMI_CHECK); | 879 miss_label, DONT_DO_SMI_CHECK); |
| 880 if (CpuFeatures::IsSupported(SSE2)) { | 880 if (CpuFeatures::IsSupported(SSE2)) { |
| 881 CpuFeatureScope use_sse2(masm, SSE2); | 881 CpuFeatureScope use_sse2(masm, SSE2); |
| 882 __ movdbl(xmm0, FieldOperand(value_reg, HeapNumber::kValueOffset)); | 882 __ movsd(xmm0, FieldOperand(value_reg, HeapNumber::kValueOffset)); |
| 883 } else { | 883 } else { |
| 884 __ fld_d(FieldOperand(value_reg, HeapNumber::kValueOffset)); | 884 __ fld_d(FieldOperand(value_reg, HeapNumber::kValueOffset)); |
| 885 } | 885 } |
| 886 | 886 |
| 887 __ bind(&do_store); | 887 __ bind(&do_store); |
| 888 if (CpuFeatures::IsSupported(SSE2)) { | 888 if (CpuFeatures::IsSupported(SSE2)) { |
| 889 CpuFeatureScope use_sse2(masm, SSE2); | 889 CpuFeatureScope use_sse2(masm, SSE2); |
| 890 __ movdbl(FieldOperand(storage_reg, HeapNumber::kValueOffset), xmm0); | 890 __ movsd(FieldOperand(storage_reg, HeapNumber::kValueOffset), xmm0); |
| 891 } else { | 891 } else { |
| 892 __ fstp_d(FieldOperand(storage_reg, HeapNumber::kValueOffset)); | 892 __ fstp_d(FieldOperand(storage_reg, HeapNumber::kValueOffset)); |
| 893 } | 893 } |
| 894 } | 894 } |
| 895 | 895 |
| 896 // Stub never generated for non-global objects that require access | 896 // Stub never generated for non-global objects that require access |
| 897 // checks. | 897 // checks. |
| 898 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); | 898 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); |
| 899 | 899 |
| 900 // Perform map transition for the receiver if necessary. | 900 // Perform map transition for the receiver if necessary. |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 994 } | 994 } |
| 995 | 995 |
| 996 // Return the value (register eax). | 996 // Return the value (register eax). |
| 997 ASSERT(value_reg.is(eax)); | 997 ASSERT(value_reg.is(eax)); |
| 998 __ ret(0); | 998 __ ret(0); |
| 999 } | 999 } |
| 1000 | 1000 |
| 1001 | 1001 |
| 1002 // Both name_reg and receiver_reg are preserved on jumps to miss_label, | 1002 // Both name_reg and receiver_reg are preserved on jumps to miss_label, |
| 1003 // but may be destroyed if store is successful. | 1003 // but may be destroyed if store is successful. |
| 1004 void BaseStoreStubCompiler::GenerateStoreField(MacroAssembler* masm, | 1004 void StoreStubCompiler::GenerateStoreField(MacroAssembler* masm, |
| 1005 Handle<JSObject> object, | 1005 Handle<JSObject> object, |
| 1006 LookupResult* lookup, | 1006 LookupResult* lookup, |
| 1007 Register receiver_reg, | 1007 Register receiver_reg, |
| 1008 Register name_reg, | 1008 Register name_reg, |
| 1009 Register value_reg, | 1009 Register value_reg, |
| 1010 Register scratch1, | 1010 Register scratch1, |
| 1011 Register scratch2, | 1011 Register scratch2, |
| 1012 Label* miss_label) { | 1012 Label* miss_label) { |
| 1013 // Stub never generated for non-global objects that require access | 1013 // Stub never generated for non-global objects that require access |
| 1014 // checks. | 1014 // checks. |
| 1015 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); | 1015 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); |
| 1016 | 1016 |
| 1017 int index = lookup->GetFieldIndex().field_index(); | 1017 int index = lookup->GetFieldIndex().field_index(); |
| 1018 | 1018 |
| 1019 // Adjust for the number of properties stored in the object. Even in the | 1019 // Adjust for the number of properties stored in the object. Even in the |
| 1020 // face of a transition we can use the old map here because the size of the | 1020 // face of a transition we can use the old map here because the size of the |
| 1021 // object and the number of in-object properties is not going to change. | 1021 // object and the number of in-object properties is not going to change. |
| 1022 index -= object->map()->inobject_properties(); | 1022 index -= object->map()->inobject_properties(); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1050 __ fild_s(Operand(esp, 0)); | 1050 __ fild_s(Operand(esp, 0)); |
| 1051 __ pop(value_reg); | 1051 __ pop(value_reg); |
| 1052 } | 1052 } |
| 1053 __ SmiTag(value_reg); | 1053 __ SmiTag(value_reg); |
| 1054 __ jmp(&do_store); | 1054 __ jmp(&do_store); |
| 1055 __ bind(&heap_number); | 1055 __ bind(&heap_number); |
| 1056 __ CheckMap(value_reg, masm->isolate()->factory()->heap_number_map(), | 1056 __ CheckMap(value_reg, masm->isolate()->factory()->heap_number_map(), |
| 1057 miss_label, DONT_DO_SMI_CHECK); | 1057 miss_label, DONT_DO_SMI_CHECK); |
| 1058 if (CpuFeatures::IsSupported(SSE2)) { | 1058 if (CpuFeatures::IsSupported(SSE2)) { |
| 1059 CpuFeatureScope use_sse2(masm, SSE2); | 1059 CpuFeatureScope use_sse2(masm, SSE2); |
| 1060 __ movdbl(xmm0, FieldOperand(value_reg, HeapNumber::kValueOffset)); | 1060 __ movsd(xmm0, FieldOperand(value_reg, HeapNumber::kValueOffset)); |
| 1061 } else { | 1061 } else { |
| 1062 __ fld_d(FieldOperand(value_reg, HeapNumber::kValueOffset)); | 1062 __ fld_d(FieldOperand(value_reg, HeapNumber::kValueOffset)); |
| 1063 } | 1063 } |
| 1064 __ bind(&do_store); | 1064 __ bind(&do_store); |
| 1065 if (CpuFeatures::IsSupported(SSE2)) { | 1065 if (CpuFeatures::IsSupported(SSE2)) { |
| 1066 CpuFeatureScope use_sse2(masm, SSE2); | 1066 CpuFeatureScope use_sse2(masm, SSE2); |
| 1067 __ movdbl(FieldOperand(scratch1, HeapNumber::kValueOffset), xmm0); | 1067 __ movsd(FieldOperand(scratch1, HeapNumber::kValueOffset), xmm0); |
| 1068 } else { | 1068 } else { |
| 1069 __ fstp_d(FieldOperand(scratch1, HeapNumber::kValueOffset)); | 1069 __ fstp_d(FieldOperand(scratch1, HeapNumber::kValueOffset)); |
| 1070 } | 1070 } |
| 1071 // Return the value (register eax). | 1071 // Return the value (register eax). |
| 1072 ASSERT(value_reg.is(eax)); | 1072 ASSERT(value_reg.is(eax)); |
| 1073 __ ret(0); | 1073 __ ret(0); |
| 1074 return; | 1074 return; |
| 1075 } | 1075 } |
| 1076 | 1076 |
| 1077 ASSERT(!FLAG_track_double_fields || !representation.IsDouble()); | 1077 ASSERT(!FLAG_track_double_fields || !representation.IsDouble()); |
| (...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1266 // If we've skipped any global objects, it's not enough to verify that | 1266 // If we've skipped any global objects, it's not enough to verify that |
| 1267 // their maps haven't changed. We also need to check that the property | 1267 // their maps haven't changed. We also need to check that the property |
| 1268 // cell for the property is still empty. | 1268 // cell for the property is still empty. |
| 1269 GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss); | 1269 GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss); |
| 1270 | 1270 |
| 1271 // Return the register containing the holder. | 1271 // Return the register containing the holder. |
| 1272 return reg; | 1272 return reg; |
| 1273 } | 1273 } |
| 1274 | 1274 |
| 1275 | 1275 |
| 1276 void BaseLoadStubCompiler::HandlerFrontendFooter(Handle<Name> name, | 1276 void LoadStubCompiler::HandlerFrontendFooter(Handle<Name> name, |
| 1277 Label* success, | 1277 Label* success, |
| 1278 Label* miss) { | 1278 Label* miss) { |
| 1279 if (!miss->is_unused()) { | 1279 if (!miss->is_unused()) { |
| 1280 __ jmp(success); | 1280 __ jmp(success); |
| 1281 __ bind(miss); | 1281 __ bind(miss); |
| 1282 TailCallBuiltin(masm(), MissBuiltin(kind())); | 1282 TailCallBuiltin(masm(), MissBuiltin(kind())); |
| 1283 } | 1283 } |
| 1284 } | 1284 } |
| 1285 | 1285 |
| 1286 | 1286 |
| 1287 void BaseStoreStubCompiler::HandlerFrontendFooter(Handle<Name> name, | 1287 void StoreStubCompiler::HandlerFrontendFooter(Handle<Name> name, |
| 1288 Label* success, | 1288 Label* success, |
| 1289 Label* miss) { | 1289 Label* miss) { |
| 1290 if (!miss->is_unused()) { | 1290 if (!miss->is_unused()) { |
| 1291 __ jmp(success); | 1291 __ jmp(success); |
| 1292 GenerateRestoreName(masm(), miss, name); | 1292 GenerateRestoreName(masm(), miss, name); |
| 1293 TailCallBuiltin(masm(), MissBuiltin(kind())); | 1293 TailCallBuiltin(masm(), MissBuiltin(kind())); |
| 1294 } | 1294 } |
| 1295 } | 1295 } |
| 1296 | 1296 |
| 1297 | 1297 |
| 1298 Register BaseLoadStubCompiler::CallbackHandlerFrontend( | 1298 Register LoadStubCompiler::CallbackHandlerFrontend( |
| 1299 Handle<JSObject> object, | 1299 Handle<JSObject> object, |
| 1300 Register object_reg, | 1300 Register object_reg, |
| 1301 Handle<JSObject> holder, | 1301 Handle<JSObject> holder, |
| 1302 Handle<Name> name, | 1302 Handle<Name> name, |
| 1303 Label* success, | 1303 Label* success, |
| 1304 Handle<Object> callback) { | 1304 Handle<Object> callback) { |
| 1305 Label miss; | 1305 Label miss; |
| 1306 | 1306 |
| 1307 Register reg = HandlerFrontendHeader(object, object_reg, holder, name, &miss); | 1307 Register reg = HandlerFrontendHeader(object, object_reg, holder, name, &miss); |
| 1308 | 1308 |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1348 } | 1348 } |
| 1349 __ cmp(scratch3(), callback); | 1349 __ cmp(scratch3(), callback); |
| 1350 __ j(not_equal, &miss); | 1350 __ j(not_equal, &miss); |
| 1351 } | 1351 } |
| 1352 | 1352 |
| 1353 HandlerFrontendFooter(name, success, &miss); | 1353 HandlerFrontendFooter(name, success, &miss); |
| 1354 return reg; | 1354 return reg; |
| 1355 } | 1355 } |
| 1356 | 1356 |
| 1357 | 1357 |
| 1358 void BaseLoadStubCompiler::NonexistentHandlerFrontend( | 1358 void LoadStubCompiler::NonexistentHandlerFrontend( |
| 1359 Handle<JSObject> object, | 1359 Handle<JSObject> object, |
| 1360 Handle<JSObject> last, | 1360 Handle<JSObject> last, |
| 1361 Handle<Name> name, | 1361 Handle<Name> name, |
| 1362 Label* success, | 1362 Label* success, |
| 1363 Handle<GlobalObject> global) { | 1363 Handle<GlobalObject> global) { |
| 1364 Label miss; | 1364 Label miss; |
| 1365 | 1365 |
| 1366 HandlerFrontendHeader(object, receiver(), last, name, &miss); | 1366 HandlerFrontendHeader(object, receiver(), last, name, &miss); |
| 1367 | 1367 |
| 1368 // If the last object in the prototype chain is a global object, | 1368 // If the last object in the prototype chain is a global object, |
| 1369 // check that the global property cell is empty. | 1369 // check that the global property cell is empty. |
| 1370 if (!global.is_null()) { | 1370 if (!global.is_null()) { |
| 1371 GenerateCheckPropertyCell(masm(), global, name, scratch2(), &miss); | 1371 GenerateCheckPropertyCell(masm(), global, name, scratch2(), &miss); |
| 1372 } | 1372 } |
| 1373 | 1373 |
| 1374 HandlerFrontendFooter(name, success, &miss); | 1374 HandlerFrontendFooter(name, success, &miss); |
| 1375 } | 1375 } |
| 1376 | 1376 |
| 1377 | 1377 |
| 1378 void BaseLoadStubCompiler::GenerateLoadField(Register reg, | 1378 void LoadStubCompiler::GenerateLoadField(Register reg, |
| 1379 Handle<JSObject> holder, | 1379 Handle<JSObject> holder, |
| 1380 PropertyIndex field, | 1380 PropertyIndex field, |
| 1381 Representation representation) { | 1381 Representation representation) { |
| 1382 if (!reg.is(receiver())) __ mov(receiver(), reg); | 1382 if (!reg.is(receiver())) __ mov(receiver(), reg); |
| 1383 if (kind() == Code::LOAD_IC) { | 1383 if (kind() == Code::LOAD_IC) { |
| 1384 LoadFieldStub stub(field.is_inobject(holder), | 1384 LoadFieldStub stub(field.is_inobject(holder), |
| 1385 field.translate(holder), | 1385 field.translate(holder), |
| 1386 representation); | 1386 representation); |
| 1387 GenerateTailCall(masm(), stub.GetCode(isolate())); | 1387 GenerateTailCall(masm(), stub.GetCode(isolate())); |
| 1388 } else { | 1388 } else { |
| 1389 KeyedLoadFieldStub stub(field.is_inobject(holder), | 1389 KeyedLoadFieldStub stub(field.is_inobject(holder), |
| 1390 field.translate(holder), | 1390 field.translate(holder), |
| 1391 representation); | 1391 representation); |
| 1392 GenerateTailCall(masm(), stub.GetCode(isolate())); | 1392 GenerateTailCall(masm(), stub.GetCode(isolate())); |
| 1393 } | 1393 } |
| 1394 } | 1394 } |
| 1395 | 1395 |
| 1396 | 1396 |
| 1397 void BaseLoadStubCompiler::GenerateLoadCallback( | 1397 void LoadStubCompiler::GenerateLoadCallback( |
| 1398 const CallOptimization& call_optimization) { | 1398 const CallOptimization& call_optimization) { |
| 1399 GenerateFastApiCall( | 1399 GenerateFastApiCall( |
| 1400 masm(), call_optimization, receiver(), scratch3(), 0, NULL); | 1400 masm(), call_optimization, receiver(), scratch3(), 0, NULL); |
| 1401 } | 1401 } |
| 1402 | 1402 |
| 1403 | 1403 |
| 1404 void BaseLoadStubCompiler::GenerateLoadCallback( | 1404 void LoadStubCompiler::GenerateLoadCallback( |
| 1405 Register reg, | 1405 Register reg, |
| 1406 Handle<ExecutableAccessorInfo> callback) { | 1406 Handle<ExecutableAccessorInfo> callback) { |
| 1407 // Insert additional parameters into the stack frame above return address. | 1407 // Insert additional parameters into the stack frame above return address. |
| 1408 ASSERT(!scratch3().is(reg)); | 1408 ASSERT(!scratch3().is(reg)); |
| 1409 __ pop(scratch3()); // Get return address to place it below. | 1409 __ pop(scratch3()); // Get return address to place it below. |
| 1410 | 1410 |
| 1411 STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 0); | 1411 STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 0); |
| 1412 STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 1); | 1412 STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 1); |
| 1413 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 2); | 1413 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 2); |
| 1414 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 3); | 1414 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 3); |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1460 | 1460 |
| 1461 __ CallApiFunctionAndReturn(getter_address, | 1461 __ CallApiFunctionAndReturn(getter_address, |
| 1462 thunk_address, | 1462 thunk_address, |
| 1463 ApiParameterOperand(2), | 1463 ApiParameterOperand(2), |
| 1464 kStackSpace, | 1464 kStackSpace, |
| 1465 Operand(ebp, 7 * kPointerSize), | 1465 Operand(ebp, 7 * kPointerSize), |
| 1466 NULL); | 1466 NULL); |
| 1467 } | 1467 } |
| 1468 | 1468 |
| 1469 | 1469 |
| 1470 void BaseLoadStubCompiler::GenerateLoadConstant(Handle<Object> value) { | 1470 void LoadStubCompiler::GenerateLoadConstant(Handle<Object> value) { |
| 1471 // Return the constant value. | 1471 // Return the constant value. |
| 1472 __ LoadObject(eax, value); | 1472 __ LoadObject(eax, value); |
| 1473 __ ret(0); | 1473 __ ret(0); |
| 1474 } | 1474 } |
| 1475 | 1475 |
| 1476 | 1476 |
| 1477 void BaseLoadStubCompiler::GenerateLoadInterceptor( | 1477 void LoadStubCompiler::GenerateLoadInterceptor( |
| 1478 Register holder_reg, | 1478 Register holder_reg, |
| 1479 Handle<JSObject> object, | 1479 Handle<JSObject> object, |
| 1480 Handle<JSObject> interceptor_holder, | 1480 Handle<JSObject> interceptor_holder, |
| 1481 LookupResult* lookup, | 1481 LookupResult* lookup, |
| 1482 Handle<Name> name) { | 1482 Handle<Name> name) { |
| 1483 ASSERT(interceptor_holder->HasNamedInterceptor()); | 1483 ASSERT(interceptor_holder->HasNamedInterceptor()); |
| 1484 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); | 1484 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); |
| 1485 | 1485 |
| 1486 // So far the most popular follow ups for interceptor loads are FIELD | 1486 // So far the most popular follow ups for interceptor loads are FIELD |
| 1487 // and CALLBACKS, so inline only them, other cases may be added | 1487 // and CALLBACKS, so inline only them, other cases may be added |
| (...skipping 902 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2390 __ mov(eax, Operand(esp, 1 * kPointerSize)); | 2390 __ mov(eax, Operand(esp, 1 * kPointerSize)); |
| 2391 | 2391 |
| 2392 // Check if the argument is a smi. | 2392 // Check if the argument is a smi. |
| 2393 Label smi; | 2393 Label smi; |
| 2394 STATIC_ASSERT(kSmiTag == 0); | 2394 STATIC_ASSERT(kSmiTag == 0); |
| 2395 __ JumpIfSmi(eax, &smi); | 2395 __ JumpIfSmi(eax, &smi); |
| 2396 | 2396 |
| 2397 // Check if the argument is a heap number and load its value into xmm0. | 2397 // Check if the argument is a heap number and load its value into xmm0. |
| 2398 Label slow; | 2398 Label slow; |
| 2399 __ CheckMap(eax, factory()->heap_number_map(), &slow, DONT_DO_SMI_CHECK); | 2399 __ CheckMap(eax, factory()->heap_number_map(), &slow, DONT_DO_SMI_CHECK); |
| 2400 __ movdbl(xmm0, FieldOperand(eax, HeapNumber::kValueOffset)); | 2400 __ movsd(xmm0, FieldOperand(eax, HeapNumber::kValueOffset)); |
| 2401 | 2401 |
| 2402 // Check if the argument is strictly positive. Note this also | 2402 // Check if the argument is strictly positive. Note this also |
| 2403 // discards NaN. | 2403 // discards NaN. |
| 2404 __ xorpd(xmm1, xmm1); | 2404 __ xorpd(xmm1, xmm1); |
| 2405 __ ucomisd(xmm0, xmm1); | 2405 __ ucomisd(xmm0, xmm1); |
| 2406 __ j(below_equal, &slow); | 2406 __ j(below_equal, &slow); |
| 2407 | 2407 |
| 2408 // Do a truncating conversion. | 2408 // Do a truncating conversion. |
| 2409 __ cvttsd2si(eax, Operand(xmm0)); | 2409 __ cvttsd2si(eax, Operand(xmm0)); |
| 2410 | 2410 |
| (...skipping 29 matching lines...) Expand all Loading... |
| 2440 // xmm2 = 0...0 | 2440 // xmm2 = 0...0 |
| 2441 __ cmpltsd(xmm2, xmm0); | 2441 __ cmpltsd(xmm2, xmm0); |
| 2442 | 2442 |
| 2443 // Subtract 1 if the argument was less than the tentative result. | 2443 // Subtract 1 if the argument was less than the tentative result. |
| 2444 __ LoadPowerOf2(xmm1, ebx, 0); | 2444 __ LoadPowerOf2(xmm1, ebx, 0); |
| 2445 __ andpd(xmm1, xmm2); | 2445 __ andpd(xmm1, xmm2); |
| 2446 __ subsd(xmm0, xmm1); | 2446 __ subsd(xmm0, xmm1); |
| 2447 | 2447 |
| 2448 // Return a new heap number. | 2448 // Return a new heap number. |
| 2449 __ AllocateHeapNumber(eax, ebx, edx, &slow); | 2449 __ AllocateHeapNumber(eax, ebx, edx, &slow); |
| 2450 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); | 2450 __ movsd(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); |
| 2451 __ ret(2 * kPointerSize); | 2451 __ ret(2 * kPointerSize); |
| 2452 | 2452 |
| 2453 // Return the argument (when it's an already round heap number). | 2453 // Return the argument (when it's an already round heap number). |
| 2454 __ bind(&already_round); | 2454 __ bind(&already_round); |
| 2455 __ mov(eax, Operand(esp, 1 * kPointerSize)); | 2455 __ mov(eax, Operand(esp, 1 * kPointerSize)); |
| 2456 __ ret(2 * kPointerSize); | 2456 __ ret(2 * kPointerSize); |
| 2457 | 2457 |
| 2458 // Tail call the full function. We do not have to patch the receiver | 2458 // Tail call the full function. We do not have to patch the receiver |
| 2459 // because the function makes no use of it. | 2459 // because the function makes no use of it. |
| 2460 __ bind(&slow); | 2460 __ bind(&slow); |
| (...skipping 646 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3107 __ cmp(name_reg, Immediate(name)); | 3107 __ cmp(name_reg, Immediate(name)); |
| 3108 __ j(not_equal, miss); | 3108 __ j(not_equal, miss); |
| 3109 } | 3109 } |
| 3110 | 3110 |
| 3111 | 3111 |
| 3112 #undef __ | 3112 #undef __ |
| 3113 #define __ ACCESS_MASM(masm) | 3113 #define __ ACCESS_MASM(masm) |
| 3114 | 3114 |
| 3115 | 3115 |
| 3116 void LoadStubCompiler::GenerateLoadViaGetter(MacroAssembler* masm, | 3116 void LoadStubCompiler::GenerateLoadViaGetter(MacroAssembler* masm, |
| 3117 Register receiver, |
| 3117 Handle<JSFunction> getter) { | 3118 Handle<JSFunction> getter) { |
| 3118 // ----------- S t a t e ------------- | |
| 3119 // -- ecx : name | |
| 3120 // -- edx : receiver | |
| 3121 // -- esp[0] : return address | |
| 3122 // ----------------------------------- | |
| 3123 { | 3119 { |
| 3124 FrameScope scope(masm, StackFrame::INTERNAL); | 3120 FrameScope scope(masm, StackFrame::INTERNAL); |
| 3125 | 3121 |
| 3126 if (!getter.is_null()) { | 3122 if (!getter.is_null()) { |
| 3127 // Call the JavaScript getter with the receiver on the stack. | 3123 // Call the JavaScript getter with the receiver on the stack. |
| 3128 __ push(edx); | 3124 __ push(receiver); |
| 3129 ParameterCount actual(0); | 3125 ParameterCount actual(0); |
| 3130 ParameterCount expected(getter); | 3126 ParameterCount expected(getter); |
| 3131 __ InvokeFunction(getter, expected, actual, | 3127 __ InvokeFunction(getter, expected, actual, |
| 3132 CALL_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); | 3128 CALL_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); |
| 3133 } else { | 3129 } else { |
| 3134 // If we generate a global code snippet for deoptimization only, remember | 3130 // If we generate a global code snippet for deoptimization only, remember |
| 3135 // the place to continue after deoptimization. | 3131 // the place to continue after deoptimization. |
| 3136 masm->isolate()->heap()->SetGetterStubDeoptPCOffset(masm->pc_offset()); | 3132 masm->isolate()->heap()->SetGetterStubDeoptPCOffset(masm->pc_offset()); |
| 3137 } | 3133 } |
| 3138 | 3134 |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3271 // ----------------------------------- | 3267 // ----------------------------------- |
| 3272 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_MissForceGeneric); | 3268 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_MissForceGeneric); |
| 3273 } | 3269 } |
| 3274 | 3270 |
| 3275 | 3271 |
| 3276 #undef __ | 3272 #undef __ |
| 3277 | 3273 |
| 3278 } } // namespace v8::internal | 3274 } } // namespace v8::internal |
| 3279 | 3275 |
| 3280 #endif // V8_TARGET_ARCH_IA32 | 3276 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |