| 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 473 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 484 STATIC_ASSERT(kFastApiCallArguments == 6); | 484 STATIC_ASSERT(kFastApiCallArguments == 6); |
| 485 __ lea(rbx, Operand(rsp, kFastApiCallArguments * kPointerSize)); | 485 __ lea(rbx, Operand(rsp, kFastApiCallArguments * kPointerSize)); |
| 486 | 486 |
| 487 // Function address is a foreign pointer outside V8's heap. | 487 // Function address is a foreign pointer outside V8's heap. |
| 488 Address function_address = v8::ToCData<Address>(api_call_info->callback()); | 488 Address function_address = v8::ToCData<Address>(api_call_info->callback()); |
| 489 bool returns_handle = | 489 bool returns_handle = |
| 490 !CallbackTable::ReturnsVoid(masm->isolate(), function_address); | 490 !CallbackTable::ReturnsVoid(masm->isolate(), function_address); |
| 491 | 491 |
| 492 #if defined(__MINGW64__) | 492 #if defined(__MINGW64__) |
| 493 Register arguments_arg = rcx; | 493 Register arguments_arg = rcx; |
| 494 Register callback_arg = rdx; | |
| 495 #elif defined(_WIN64) | 494 #elif defined(_WIN64) |
| 496 // Win64 uses first register--rcx--for returned value. | 495 // Win64 uses first register--rcx--for returned value. |
| 497 Register arguments_arg = returns_handle ? rdx : rcx; | 496 Register arguments_arg = returns_handle ? rdx : rcx; |
| 498 Register callback_arg = returns_handle ? r8 : rdx; | |
| 499 #else | 497 #else |
| 500 Register arguments_arg = rdi; | 498 Register arguments_arg = rdi; |
| 501 Register callback_arg = rsi; | |
| 502 #endif | 499 #endif |
| 503 | 500 |
| 504 // Allocate the v8::Arguments structure in the arguments' space since | 501 // Allocate the v8::Arguments structure in the arguments' space since |
| 505 // it's not controlled by GC. | 502 // it's not controlled by GC. |
| 506 const int kApiStackSpace = 4; | 503 const int kApiStackSpace = 4; |
| 507 | 504 |
| 508 __ PrepareCallApiFunction(kApiStackSpace, returns_handle); | 505 __ PrepareCallApiFunction(kApiStackSpace, returns_handle); |
| 509 | 506 |
| 510 __ movq(StackSpaceOperand(0), rbx); // v8::Arguments::implicit_args_. | 507 __ movq(StackSpaceOperand(0), rbx); // v8::Arguments::implicit_args_. |
| 511 __ addq(rbx, Immediate(argc * kPointerSize)); | 508 __ addq(rbx, Immediate(argc * kPointerSize)); |
| 512 __ movq(StackSpaceOperand(1), rbx); // v8::Arguments::values_. | 509 __ movq(StackSpaceOperand(1), rbx); // v8::Arguments::values_. |
| 513 __ Set(StackSpaceOperand(2), argc); // v8::Arguments::length_. | 510 __ Set(StackSpaceOperand(2), argc); // v8::Arguments::length_. |
| 514 // v8::Arguments::is_construct_call_. | 511 // v8::Arguments::is_construct_call_. |
| 515 __ Set(StackSpaceOperand(3), 0); | 512 __ Set(StackSpaceOperand(3), 0); |
| 516 | 513 |
| 517 // v8::InvocationCallback's argument. | 514 // v8::InvocationCallback's argument. |
| 518 __ lea(arguments_arg, StackSpaceOperand(0)); | 515 __ lea(arguments_arg, StackSpaceOperand(0)); |
| 519 | 516 |
| 520 Address thunk_address = returns_handle | |
| 521 ? FUNCTION_ADDR(&InvokeInvocationCallback) | |
| 522 : FUNCTION_ADDR(&InvokeFunctionCallback); | |
| 523 | |
| 524 __ CallApiFunctionAndReturn(function_address, | 517 __ CallApiFunctionAndReturn(function_address, |
| 525 thunk_address, | |
| 526 callback_arg, | |
| 527 argc + kFastApiCallArguments + 1, | 518 argc + kFastApiCallArguments + 1, |
| 528 returns_handle, | 519 returns_handle, |
| 529 kFastApiCallArguments + 1); | 520 kFastApiCallArguments + 1); |
| 530 } | 521 } |
| 531 | 522 |
| 532 | 523 |
| 533 class CallInterceptorCompiler BASE_EMBEDDED { | 524 class CallInterceptorCompiler BASE_EMBEDDED { |
| 534 public: | 525 public: |
| 535 CallInterceptorCompiler(StubCompiler* stub_compiler, | 526 CallInterceptorCompiler(StubCompiler* stub_compiler, |
| 536 const ParameterCount& arguments, | 527 const ParameterCount& arguments, |
| (...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 819 miss_restore_name); | 810 miss_restore_name); |
| 820 } else if (!holder->HasFastProperties() && !holder->IsJSGlobalProxy()) { | 811 } else if (!holder->HasFastProperties() && !holder->IsJSGlobalProxy()) { |
| 821 GenerateDictionaryNegativeLookup( | 812 GenerateDictionaryNegativeLookup( |
| 822 masm, miss_restore_name, holder_reg, name, scratch1, scratch2); | 813 masm, miss_restore_name, holder_reg, name, scratch1, scratch2); |
| 823 } | 814 } |
| 824 } | 815 } |
| 825 } | 816 } |
| 826 | 817 |
| 827 Register storage_reg = name_reg; | 818 Register storage_reg = name_reg; |
| 828 | 819 |
| 829 if (details.type() == CONSTANT_FUNCTION) { | 820 if (FLAG_track_fields && representation.IsSmi()) { |
| 830 Handle<HeapObject> constant( | |
| 831 HeapObject::cast(descriptors->GetValue(descriptor))); | |
| 832 __ LoadHeapObject(scratch1, constant); | |
| 833 __ cmpq(value_reg, scratch1); | |
| 834 __ j(not_equal, miss_restore_name); | |
| 835 } else if (FLAG_track_fields && representation.IsSmi()) { | |
| 836 __ JumpIfNotSmi(value_reg, miss_restore_name); | 821 __ JumpIfNotSmi(value_reg, miss_restore_name); |
| 837 } else if (FLAG_track_heap_object_fields && representation.IsHeapObject()) { | 822 } else if (FLAG_track_heap_object_fields && representation.IsHeapObject()) { |
| 838 __ JumpIfSmi(value_reg, miss_restore_name); | 823 __ JumpIfSmi(value_reg, miss_restore_name); |
| 839 } else if (FLAG_track_double_fields && representation.IsDouble()) { | 824 } else if (FLAG_track_double_fields && representation.IsDouble()) { |
| 840 Label do_store, heap_number; | 825 Label do_store, heap_number; |
| 841 __ AllocateHeapNumber(storage_reg, scratch1, slow); | 826 __ AllocateHeapNumber(storage_reg, scratch1, slow); |
| 842 | 827 |
| 843 __ JumpIfNotSmi(value_reg, &heap_number); | 828 __ JumpIfNotSmi(value_reg, &heap_number); |
| 844 __ SmiToInteger32(scratch1, value_reg); | 829 __ SmiToInteger32(scratch1, value_reg); |
| 845 __ cvtlsi2sd(xmm0, scratch1); | 830 __ cvtlsi2sd(xmm0, scratch1); |
| 846 __ jmp(&do_store); | 831 __ jmp(&do_store); |
| 847 | 832 |
| 848 __ bind(&heap_number); | 833 __ bind(&heap_number); |
| 849 __ CheckMap(value_reg, masm->isolate()->factory()->heap_number_map(), | 834 __ CheckMap(value_reg, masm->isolate()->factory()->heap_number_map(), |
| 850 miss_restore_name, DONT_DO_SMI_CHECK); | 835 miss_restore_name, DONT_DO_SMI_CHECK); |
| 851 __ movsd(xmm0, FieldOperand(value_reg, HeapNumber::kValueOffset)); | 836 __ movsd(xmm0, FieldOperand(value_reg, HeapNumber::kValueOffset)); |
| 852 | 837 |
| 853 __ bind(&do_store); | 838 __ bind(&do_store); |
| 854 __ movsd(FieldOperand(storage_reg, HeapNumber::kValueOffset), xmm0); | 839 __ movsd(FieldOperand(storage_reg, HeapNumber::kValueOffset), xmm0); |
| 855 } | 840 } |
| 856 | 841 |
| 857 // Stub never generated for non-global objects that require access | 842 // Stub never generated for non-global objects that require access |
| 858 // checks. | 843 // checks. |
| 859 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); | 844 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); |
| 860 | 845 |
| 861 // Perform map transition for the receiver if necessary. | 846 // Perform map transition for the receiver if necessary. |
| 862 if (details.type() == FIELD && | 847 if (object->map()->unused_property_fields() == 0) { |
| 863 object->map()->unused_property_fields() == 0) { | |
| 864 // The properties must be extended before we can store the value. | 848 // The properties must be extended before we can store the value. |
| 865 // We jump to a runtime call that extends the properties array. | 849 // We jump to a runtime call that extends the properties array. |
| 866 __ pop(scratch1); // Return address. | 850 __ pop(scratch1); // Return address. |
| 867 __ push(receiver_reg); | 851 __ push(receiver_reg); |
| 868 __ Push(transition); | 852 __ Push(transition); |
| 869 __ push(value_reg); | 853 __ push(value_reg); |
| 870 __ push(scratch1); | 854 __ push(scratch1); |
| 871 __ TailCallExternalReference( | 855 __ TailCallExternalReference( |
| 872 ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage), | 856 ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage), |
| 873 masm->isolate()), | 857 masm->isolate()), |
| 874 3, | 858 3, |
| 875 1); | 859 1); |
| 876 return; | 860 return; |
| 877 } | 861 } |
| 878 | 862 |
| 879 // Update the map of the object. | 863 // Update the map of the object. |
| 880 __ Move(scratch1, transition); | 864 __ Move(scratch1, transition); |
| 881 __ movq(FieldOperand(receiver_reg, HeapObject::kMapOffset), scratch1); | 865 __ movq(FieldOperand(receiver_reg, HeapObject::kMapOffset), scratch1); |
| 882 | 866 |
| 883 // Update the write barrier for the map field. | 867 // Update the write barrier for the map field. |
| 884 __ RecordWriteField(receiver_reg, | 868 __ RecordWriteField(receiver_reg, |
| 885 HeapObject::kMapOffset, | 869 HeapObject::kMapOffset, |
| 886 scratch1, | 870 scratch1, |
| 887 scratch2, | 871 scratch2, |
| 888 kDontSaveFPRegs, | 872 kDontSaveFPRegs, |
| 889 OMIT_REMEMBERED_SET, | 873 OMIT_REMEMBERED_SET, |
| 890 OMIT_SMI_CHECK); | 874 OMIT_SMI_CHECK); |
| 891 | 875 |
| 892 if (details.type() == CONSTANT_FUNCTION) return; | |
| 893 | |
| 894 int index = transition->instance_descriptors()->GetFieldIndex( | 876 int index = transition->instance_descriptors()->GetFieldIndex( |
| 895 transition->LastAdded()); | 877 transition->LastAdded()); |
| 896 | 878 |
| 897 // Adjust for the number of properties stored in the object. Even in the | 879 // Adjust for the number of properties stored in the object. Even in the |
| 898 // face of a transition we can use the old map here because the size of the | 880 // face of a transition we can use the old map here because the size of the |
| 899 // object and the number of in-object properties is not going to change. | 881 // object and the number of in-object properties is not going to change. |
| 900 index -= object->map()->inobject_properties(); | 882 index -= object->map()->inobject_properties(); |
| 901 | 883 |
| 902 // TODO(verwaest): Share this code as a code stub. | 884 // TODO(verwaest): Share this code as a code stub. |
| 903 SmiCheck smi_check = representation.IsTagged() | 885 SmiCheck smi_check = representation.IsTagged() |
| (...skipping 425 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1329 __ PushAddress(ExternalReference::isolate_address(isolate())); | 1311 __ PushAddress(ExternalReference::isolate_address(isolate())); |
| 1330 __ push(name()); // name | 1312 __ push(name()); // name |
| 1331 // Save a pointer to where we pushed the arguments pointer. This will be | 1313 // Save a pointer to where we pushed the arguments pointer. This will be |
| 1332 // passed as the const ExecutableAccessorInfo& to the C++ callback. | 1314 // passed as the const ExecutableAccessorInfo& to the C++ callback. |
| 1333 | 1315 |
| 1334 Address getter_address = v8::ToCData<Address>(callback->getter()); | 1316 Address getter_address = v8::ToCData<Address>(callback->getter()); |
| 1335 bool returns_handle = | 1317 bool returns_handle = |
| 1336 !CallbackTable::ReturnsVoid(isolate(), getter_address); | 1318 !CallbackTable::ReturnsVoid(isolate(), getter_address); |
| 1337 | 1319 |
| 1338 #if defined(__MINGW64__) | 1320 #if defined(__MINGW64__) |
| 1339 Register getter_arg = r8; | |
| 1340 Register accessor_info_arg = rdx; | 1321 Register accessor_info_arg = rdx; |
| 1341 Register name_arg = rcx; | 1322 Register name_arg = rcx; |
| 1342 #elif defined(_WIN64) | 1323 #elif defined(_WIN64) |
| 1343 // Win64 uses first register--rcx--for returned value. | 1324 // Win64 uses first register--rcx--for returned value. |
| 1344 Register getter_arg = returns_handle ? r9 : r8; | |
| 1345 Register accessor_info_arg = returns_handle ? r8 : rdx; | 1325 Register accessor_info_arg = returns_handle ? r8 : rdx; |
| 1346 Register name_arg = returns_handle ? rdx : rcx; | 1326 Register name_arg = returns_handle ? rdx : rcx; |
| 1347 #else | 1327 #else |
| 1348 Register getter_arg = rdx; | |
| 1349 Register accessor_info_arg = rsi; | 1328 Register accessor_info_arg = rsi; |
| 1350 Register name_arg = rdi; | 1329 Register name_arg = rdi; |
| 1351 #endif | 1330 #endif |
| 1352 | 1331 |
| 1353 ASSERT(!name_arg.is(scratch2())); | 1332 ASSERT(!name_arg.is(scratch2())); |
| 1354 __ movq(name_arg, rsp); | 1333 __ movq(name_arg, rsp); |
| 1355 __ push(scratch2()); // Restore return address. | 1334 __ push(scratch2()); // Restore return address. |
| 1356 | 1335 |
| 1357 // v8::Arguments::values_ and handler for name. | 1336 // v8::Arguments::values_ and handler for name. |
| 1358 const int kStackSpace = PropertyCallbackArguments::kArgsLength + 1; | 1337 const int kStackSpace = PropertyCallbackArguments::kArgsLength + 1; |
| 1359 | 1338 |
| 1360 // Allocate v8::AccessorInfo in non-GCed stack space. | 1339 // Allocate v8::AccessorInfo in non-GCed stack space. |
| 1361 const int kArgStackSpace = 1; | 1340 const int kArgStackSpace = 1; |
| 1362 | 1341 |
| 1363 __ PrepareCallApiFunction(kArgStackSpace, returns_handle); | 1342 __ PrepareCallApiFunction(kArgStackSpace, returns_handle); |
| 1364 STATIC_ASSERT(PropertyCallbackArguments::kArgsLength == 6); | 1343 STATIC_ASSERT(PropertyCallbackArguments::kArgsLength == 6); |
| 1365 __ lea(rax, Operand(name_arg, 6 * kPointerSize)); | 1344 __ lea(rax, Operand(name_arg, 6 * kPointerSize)); |
| 1366 | 1345 |
| 1367 // v8::AccessorInfo::args_. | 1346 // v8::AccessorInfo::args_. |
| 1368 __ movq(StackSpaceOperand(0), rax); | 1347 __ movq(StackSpaceOperand(0), rax); |
| 1369 | 1348 |
| 1370 // The context register (rsi) has been saved in PrepareCallApiFunction and | 1349 // The context register (rsi) has been saved in PrepareCallApiFunction and |
| 1371 // could be used to pass arguments. | 1350 // could be used to pass arguments. |
| 1372 __ lea(accessor_info_arg, StackSpaceOperand(0)); | 1351 __ lea(accessor_info_arg, StackSpaceOperand(0)); |
| 1373 | 1352 |
| 1374 Address thunk_address = returns_handle | |
| 1375 ? FUNCTION_ADDR(&InvokeAccessorGetter) | |
| 1376 : FUNCTION_ADDR(&InvokeAccessorGetterCallback); | |
| 1377 | |
| 1378 __ CallApiFunctionAndReturn(getter_address, | 1353 __ CallApiFunctionAndReturn(getter_address, |
| 1379 thunk_address, | |
| 1380 getter_arg, | |
| 1381 kStackSpace, | 1354 kStackSpace, |
| 1382 returns_handle, | 1355 returns_handle, |
| 1383 5); | 1356 5); |
| 1384 } | 1357 } |
| 1385 | 1358 |
| 1386 | 1359 |
| 1387 void BaseLoadStubCompiler::GenerateLoadConstant(Handle<JSFunction> value) { | 1360 void BaseLoadStubCompiler::GenerateLoadConstant(Handle<JSFunction> value) { |
| 1388 // Return the constant value. | 1361 // Return the constant value. |
| 1389 __ LoadHeapObject(rax, value); | 1362 __ LoadHeapObject(rax, value); |
| 1390 __ ret(0); | 1363 __ ret(0); |
| (...skipping 2122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3513 TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Slow); | 3486 TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Slow); |
| 3514 } | 3487 } |
| 3515 } | 3488 } |
| 3516 | 3489 |
| 3517 | 3490 |
| 3518 #undef __ | 3491 #undef __ |
| 3519 | 3492 |
| 3520 } } // namespace v8::internal | 3493 } } // namespace v8::internal |
| 3521 | 3494 |
| 3522 #endif // V8_TARGET_ARCH_X64 | 3495 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |