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 |