OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. |
6 #if defined(TARGET_ARCH_X64) | 6 #if defined(TARGET_ARCH_X64) |
7 | 7 |
8 #include "vm/flow_graph_compiler.h" | 8 #include "vm/flow_graph_compiler.h" |
9 | 9 |
10 #include "lib/error.h" | 10 #include "lib/error.h" |
(...skipping 875 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
886 __ movq(RAX, argument_addr); | 886 __ movq(RAX, argument_addr); |
887 __ movq(copy_addr, RAX); | 887 __ movq(copy_addr, RAX); |
888 __ Bind(&loop_condition); | 888 __ Bind(&loop_condition); |
889 __ decq(RCX); | 889 __ decq(RCX); |
890 __ j(POSITIVE, &loop, Assembler::kNearJump); | 890 __ j(POSITIVE, &loop, Assembler::kNearJump); |
891 | 891 |
892 // Copy or initialize optional named arguments. | 892 // Copy or initialize optional named arguments. |
893 const Immediate& raw_null = | 893 const Immediate& raw_null = |
894 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 894 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
895 Label all_arguments_processed; | 895 Label all_arguments_processed; |
| 896 #ifdef DEBUG |
| 897 const bool check_correct_named_args = true; |
| 898 #else |
| 899 const bool check_correct_named_args = function.IsClosureFunction(); |
| 900 #endif |
896 if (num_opt_named_params > 0) { | 901 if (num_opt_named_params > 0) { |
897 // Start by alphabetically sorting the names of the optional parameters. | 902 // Start by alphabetically sorting the names of the optional parameters. |
898 LocalVariable** opt_param = new LocalVariable*[num_opt_named_params]; | 903 LocalVariable** opt_param = new LocalVariable*[num_opt_named_params]; |
899 int* opt_param_position = new int[num_opt_named_params]; | 904 int* opt_param_position = new int[num_opt_named_params]; |
900 for (int pos = num_fixed_params; pos < num_params; pos++) { | 905 for (int pos = num_fixed_params; pos < num_params; pos++) { |
901 LocalVariable* parameter = scope->VariableAt(pos); | 906 LocalVariable* parameter = scope->VariableAt(pos); |
902 const String& opt_param_name = parameter->name(); | 907 const String& opt_param_name = parameter->name(); |
903 int i = pos - num_fixed_params; | 908 int i = pos - num_fixed_params; |
904 while (--i >= 0) { | 909 while (--i >= 0) { |
905 LocalVariable* param_i = opt_param[i]; | 910 LocalVariable* param_i = opt_param[i]; |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
953 // Assign RAX to fp[kFirstLocalSlotFromFp - param_pos]. | 958 // Assign RAX to fp[kFirstLocalSlotFromFp - param_pos]. |
954 // We do not use the final allocation index of the variable here, i.e. | 959 // We do not use the final allocation index of the variable here, i.e. |
955 // scope->VariableAt(i)->index(), because captured variables still need | 960 // scope->VariableAt(i)->index(), because captured variables still need |
956 // to be copied to the context that is not yet allocated. | 961 // to be copied to the context that is not yet allocated. |
957 const intptr_t computed_param_pos = kFirstLocalSlotFromFp - param_pos; | 962 const intptr_t computed_param_pos = kFirstLocalSlotFromFp - param_pos; |
958 const Address param_addr(RBP, computed_param_pos * kWordSize); | 963 const Address param_addr(RBP, computed_param_pos * kWordSize); |
959 __ movq(param_addr, RAX); | 964 __ movq(param_addr, RAX); |
960 } | 965 } |
961 delete[] opt_param; | 966 delete[] opt_param; |
962 delete[] opt_param_position; | 967 delete[] opt_param_position; |
963 // Check that RDI now points to the null terminator in the array descriptor. | 968 if (check_correct_named_args) { |
964 __ cmpq(Address(RDI, 0), raw_null); | 969 // Check that RDI now points to the null terminator in the arguments |
965 __ j(EQUAL, &all_arguments_processed, Assembler::kNearJump); | 970 // descriptor. |
| 971 __ cmpq(Address(RDI, 0), raw_null); |
| 972 __ j(EQUAL, &all_arguments_processed, Assembler::kNearJump); |
| 973 } |
966 } else { | 974 } else { |
967 ASSERT(num_opt_pos_params > 0); | 975 ASSERT(num_opt_pos_params > 0); |
968 __ movq(RCX, | 976 __ movq(RCX, |
969 FieldAddress(R10, ArgumentsDescriptor::positional_count_offset())); | 977 FieldAddress(R10, ArgumentsDescriptor::positional_count_offset())); |
970 __ SmiUntag(RCX); | 978 __ SmiUntag(RCX); |
971 for (int i = 0; i < num_opt_pos_params; i++) { | 979 for (int i = 0; i < num_opt_pos_params; i++) { |
972 Label next_parameter; | 980 Label next_parameter; |
973 // Handle this optional positional parameter only if k or fewer positional | 981 // Handle this optional positional parameter only if k or fewer positional |
974 // arguments have been passed, where k is param_pos, the position of this | 982 // arguments have been passed, where k is param_pos, the position of this |
975 // optional parameter in the formal parameter list. | 983 // optional parameter in the formal parameter list. |
976 const int param_pos = num_fixed_params + i; | 984 const int param_pos = num_fixed_params + i; |
977 __ cmpq(RCX, Immediate(param_pos)); | 985 __ cmpq(RCX, Immediate(param_pos)); |
978 __ j(GREATER, &next_parameter, Assembler::kNearJump); | 986 __ j(GREATER, &next_parameter, Assembler::kNearJump); |
979 // Load RAX with default argument. | 987 // Load RAX with default argument. |
980 const Object& value = Object::ZoneHandle( | 988 const Object& value = Object::ZoneHandle( |
981 parsed_function().default_parameter_values().At(i)); | 989 parsed_function().default_parameter_values().At(i)); |
982 __ LoadObject(RAX, value); | 990 __ LoadObject(RAX, value); |
983 // Assign RAX to fp[kFirstLocalSlotFromFp - param_pos]. | 991 // Assign RAX to fp[kFirstLocalSlotFromFp - param_pos]. |
984 // We do not use the final allocation index of the variable here, i.e. | 992 // We do not use the final allocation index of the variable here, i.e. |
985 // scope->VariableAt(i)->index(), because captured variables still need | 993 // scope->VariableAt(i)->index(), because captured variables still need |
986 // to be copied to the context that is not yet allocated. | 994 // to be copied to the context that is not yet allocated. |
987 const intptr_t computed_param_pos = kFirstLocalSlotFromFp - param_pos; | 995 const intptr_t computed_param_pos = kFirstLocalSlotFromFp - param_pos; |
988 const Address param_addr(RBP, computed_param_pos * kWordSize); | 996 const Address param_addr(RBP, computed_param_pos * kWordSize); |
989 __ movq(param_addr, RAX); | 997 __ movq(param_addr, RAX); |
990 __ Bind(&next_parameter); | 998 __ Bind(&next_parameter); |
991 } | 999 } |
992 __ movq(RBX, FieldAddress(R10, ArgumentsDescriptor::count_offset())); | 1000 if (check_correct_named_args) { |
993 __ SmiUntag(RBX); | 1001 __ movq(RBX, FieldAddress(R10, ArgumentsDescriptor::count_offset())); |
994 // Check that RCX equals RBX, i.e. no named arguments passed. | 1002 __ SmiUntag(RBX); |
995 __ cmpq(RCX, RBX); | 1003 // Check that RCX equals RBX, i.e. no named arguments passed. |
996 __ j(EQUAL, &all_arguments_processed, Assembler::kNearJump); | 1004 __ cmpq(RCX, RBX); |
| 1005 __ j(EQUAL, &all_arguments_processed, Assembler::kNearJump); |
| 1006 } |
997 } | 1007 } |
998 | 1008 |
999 __ Bind(&wrong_num_arguments); | 1009 __ Bind(&wrong_num_arguments); |
1000 // Invoke noSuchMethod function passing the original name of the function. | 1010 if (function.IsClosureFunction()) { |
1001 // If the function is a closure function, use "call" as the original name. | 1011 // Invoke noSuchMethod function passing "call" as the original name. |
1002 const String& name = String::Handle( | 1012 const int kNumArgsChecked = 1; |
1003 function.IsClosureFunction() ? Symbols::Call().raw() : function.name()); | 1013 const ICData& ic_data = ICData::ZoneHandle( |
1004 const int kNumArgsChecked = 1; | 1014 ICData::New(function, Symbols::Call(), Object::null_array(), |
1005 const ICData& ic_data = ICData::ZoneHandle( | 1015 Isolate::kNoDeoptId, kNumArgsChecked)); |
1006 ICData::New(function, name, Object::null_array(), | 1016 __ LoadObject(RBX, ic_data); |
1007 Isolate::kNoDeoptId, kNumArgsChecked)); | 1017 __ LeaveFrame(); // The arguments are still on the stack. |
1008 __ LoadObject(RBX, ic_data); | 1018 __ jmp(&StubCode::CallNoSuchMethodFunctionLabel()); |
1009 __ LeaveFrame(); // The arguments are still on the stack. | 1019 // The noSuchMethod call may return to the caller, but not here. |
1010 __ jmp(&StubCode::CallNoSuchMethodFunctionLabel()); | 1020 __ int3(); |
1011 // The noSuchMethod call may return to the caller, but not here. | 1021 } else if (check_correct_named_args) { |
1012 __ int3(); | 1022 __ Stop("Wrong arguments"); |
| 1023 } |
1013 | 1024 |
1014 __ Bind(&all_arguments_processed); | 1025 __ Bind(&all_arguments_processed); |
1015 // Nullify originally passed arguments only after they have been copied and | 1026 // Nullify originally passed arguments only after they have been copied and |
1016 // checked, otherwise noSuchMethod would not see their original values. | 1027 // checked, otherwise noSuchMethod would not see their original values. |
1017 // This step can be skipped in case we decide that formal parameters are | 1028 // This step can be skipped in case we decide that formal parameters are |
1018 // implicitly final, since garbage collecting the unmodified value is not | 1029 // implicitly final, since garbage collecting the unmodified value is not |
1019 // an issue anymore. | 1030 // an issue anymore. |
1020 | 1031 |
1021 // R10 : arguments descriptor array. | 1032 // R10 : arguments descriptor array. |
1022 __ movq(RCX, FieldAddress(R10, ArgumentsDescriptor::count_offset())); | 1033 __ movq(RCX, FieldAddress(R10, ArgumentsDescriptor::count_offset())); |
(...skipping 866 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1889 __ movups(reg, Address(RSP, 0)); | 1900 __ movups(reg, Address(RSP, 0)); |
1890 __ addq(RSP, Immediate(kFpuRegisterSize)); | 1901 __ addq(RSP, Immediate(kFpuRegisterSize)); |
1891 } | 1902 } |
1892 | 1903 |
1893 | 1904 |
1894 #undef __ | 1905 #undef __ |
1895 | 1906 |
1896 } // namespace dart | 1907 } // namespace dart |
1897 | 1908 |
1898 #endif // defined TARGET_ARCH_X64 | 1909 #endif // defined TARGET_ARCH_X64 |
OLD | NEW |