| 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_IA32. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. |
| 6 #if defined(TARGET_ARCH_IA32) | 6 #if defined(TARGET_ARCH_IA32) |
| 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 881 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 892 __ movl(EAX, argument_addr); | 892 __ movl(EAX, argument_addr); |
| 893 __ movl(copy_addr, EAX); | 893 __ movl(copy_addr, EAX); |
| 894 __ Bind(&loop_condition); | 894 __ Bind(&loop_condition); |
| 895 __ decl(ECX); | 895 __ decl(ECX); |
| 896 __ j(POSITIVE, &loop, Assembler::kNearJump); | 896 __ j(POSITIVE, &loop, Assembler::kNearJump); |
| 897 | 897 |
| 898 // Copy or initialize optional named arguments. | 898 // Copy or initialize optional named arguments. |
| 899 const Immediate& raw_null = | 899 const Immediate& raw_null = |
| 900 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 900 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 901 Label all_arguments_processed; | 901 Label all_arguments_processed; |
| 902 #ifdef DEBUG |
| 903 const bool check_correct_named_args = true; |
| 904 #else |
| 905 const bool check_correct_named_args = function.IsClosureFunction(); |
| 906 #endif |
| 902 if (num_opt_named_params > 0) { | 907 if (num_opt_named_params > 0) { |
| 903 // Start by alphabetically sorting the names of the optional parameters. | 908 // Start by alphabetically sorting the names of the optional parameters. |
| 904 LocalVariable** opt_param = new LocalVariable*[num_opt_named_params]; | 909 LocalVariable** opt_param = new LocalVariable*[num_opt_named_params]; |
| 905 int* opt_param_position = new int[num_opt_named_params]; | 910 int* opt_param_position = new int[num_opt_named_params]; |
| 906 for (int pos = num_fixed_params; pos < num_params; pos++) { | 911 for (int pos = num_fixed_params; pos < num_params; pos++) { |
| 907 LocalVariable* parameter = scope->VariableAt(pos); | 912 LocalVariable* parameter = scope->VariableAt(pos); |
| 908 const String& opt_param_name = parameter->name(); | 913 const String& opt_param_name = parameter->name(); |
| 909 int i = pos - num_fixed_params; | 914 int i = pos - num_fixed_params; |
| 910 while (--i >= 0) { | 915 while (--i >= 0) { |
| 911 LocalVariable* param_i = opt_param[i]; | 916 LocalVariable* param_i = opt_param[i]; |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 959 // Assign EAX to fp[kFirstLocalSlotFromFp - param_pos]. | 964 // Assign EAX to fp[kFirstLocalSlotFromFp - param_pos]. |
| 960 // We do not use the final allocation index of the variable here, i.e. | 965 // We do not use the final allocation index of the variable here, i.e. |
| 961 // scope->VariableAt(i)->index(), because captured variables still need | 966 // scope->VariableAt(i)->index(), because captured variables still need |
| 962 // to be copied to the context that is not yet allocated. | 967 // to be copied to the context that is not yet allocated. |
| 963 const intptr_t computed_param_pos = kFirstLocalSlotFromFp - param_pos; | 968 const intptr_t computed_param_pos = kFirstLocalSlotFromFp - param_pos; |
| 964 const Address param_addr(EBP, computed_param_pos * kWordSize); | 969 const Address param_addr(EBP, computed_param_pos * kWordSize); |
| 965 __ movl(param_addr, EAX); | 970 __ movl(param_addr, EAX); |
| 966 } | 971 } |
| 967 delete[] opt_param; | 972 delete[] opt_param; |
| 968 delete[] opt_param_position; | 973 delete[] opt_param_position; |
| 969 // Check that EDI now points to the null terminator in the array descriptor. | 974 if (check_correct_named_args) { |
| 970 __ cmpl(Address(EDI, 0), raw_null); | 975 // Check that EDI now points to the null terminator in the arguments |
| 971 __ j(EQUAL, &all_arguments_processed, Assembler::kNearJump); | 976 // descriptor. |
| 977 __ cmpl(Address(EDI, 0), raw_null); |
| 978 __ j(EQUAL, &all_arguments_processed, Assembler::kNearJump); |
| 979 } |
| 972 } else { | 980 } else { |
| 973 ASSERT(num_opt_pos_params > 0); | 981 ASSERT(num_opt_pos_params > 0); |
| 974 __ movl(ECX, | 982 __ movl(ECX, |
| 975 FieldAddress(EDX, ArgumentsDescriptor::positional_count_offset())); | 983 FieldAddress(EDX, ArgumentsDescriptor::positional_count_offset())); |
| 976 __ SmiUntag(ECX); | 984 __ SmiUntag(ECX); |
| 977 for (int i = 0; i < num_opt_pos_params; i++) { | 985 for (int i = 0; i < num_opt_pos_params; i++) { |
| 978 Label next_parameter; | 986 Label next_parameter; |
| 979 // Handle this optional positional parameter only if k or fewer positional | 987 // Handle this optional positional parameter only if k or fewer positional |
| 980 // arguments have been passed, where k is param_pos, the position of this | 988 // arguments have been passed, where k is param_pos, the position of this |
| 981 // optional parameter in the formal parameter list. | 989 // optional parameter in the formal parameter list. |
| 982 const int param_pos = num_fixed_params + i; | 990 const int param_pos = num_fixed_params + i; |
| 983 __ cmpl(ECX, Immediate(param_pos)); | 991 __ cmpl(ECX, Immediate(param_pos)); |
| 984 __ j(GREATER, &next_parameter, Assembler::kNearJump); | 992 __ j(GREATER, &next_parameter, Assembler::kNearJump); |
| 985 // Load EAX with default argument. | 993 // Load EAX with default argument. |
| 986 const Object& value = Object::ZoneHandle( | 994 const Object& value = Object::ZoneHandle( |
| 987 parsed_function().default_parameter_values().At(i)); | 995 parsed_function().default_parameter_values().At(i)); |
| 988 __ LoadObject(EAX, value); | 996 __ LoadObject(EAX, value); |
| 989 // Assign EAX to fp[kFirstLocalSlotFromFp - param_pos]. | 997 // Assign EAX to fp[kFirstLocalSlotFromFp - param_pos]. |
| 990 // We do not use the final allocation index of the variable here, i.e. | 998 // We do not use the final allocation index of the variable here, i.e. |
| 991 // scope->VariableAt(i)->index(), because captured variables still need | 999 // scope->VariableAt(i)->index(), because captured variables still need |
| 992 // to be copied to the context that is not yet allocated. | 1000 // to be copied to the context that is not yet allocated. |
| 993 const intptr_t computed_param_pos = kFirstLocalSlotFromFp - param_pos; | 1001 const intptr_t computed_param_pos = kFirstLocalSlotFromFp - param_pos; |
| 994 const Address param_addr(EBP, computed_param_pos * kWordSize); | 1002 const Address param_addr(EBP, computed_param_pos * kWordSize); |
| 995 __ movl(param_addr, EAX); | 1003 __ movl(param_addr, EAX); |
| 996 __ Bind(&next_parameter); | 1004 __ Bind(&next_parameter); |
| 997 } | 1005 } |
| 998 __ movl(EBX, FieldAddress(EDX, ArgumentsDescriptor::count_offset())); | 1006 if (check_correct_named_args) { |
| 999 __ SmiUntag(EBX); | 1007 __ movl(EBX, FieldAddress(EDX, ArgumentsDescriptor::count_offset())); |
| 1000 // Check that ECX equals EBX, i.e. no named arguments passed. | 1008 __ SmiUntag(EBX); |
| 1001 __ cmpl(ECX, EBX); | 1009 // Check that ECX equals EBX, i.e. no named arguments passed. |
| 1002 __ j(EQUAL, &all_arguments_processed, Assembler::kNearJump); | 1010 __ cmpl(ECX, EBX); |
| 1011 __ j(EQUAL, &all_arguments_processed, Assembler::kNearJump); |
| 1012 } |
| 1003 } | 1013 } |
| 1004 | 1014 |
| 1005 __ Bind(&wrong_num_arguments); | 1015 __ Bind(&wrong_num_arguments); |
| 1006 // Invoke noSuchMethod function passing the original name of the function. | 1016 if (function.IsClosureFunction()) { |
| 1007 // If the function is a closure function, use "call" as the original name. | 1017 // Invoke noSuchMethod function passing "call" as the original name. |
| 1008 const String& name = String::Handle( | 1018 const int kNumArgsChecked = 1; |
| 1009 function.IsClosureFunction() ? Symbols::Call().raw() : function.name()); | 1019 const ICData& ic_data = ICData::ZoneHandle( |
| 1010 const int kNumArgsChecked = 1; | 1020 ICData::New(function, Symbols::Call(), Object::null_array(), |
| 1011 const ICData& ic_data = ICData::ZoneHandle( | 1021 Isolate::kNoDeoptId, kNumArgsChecked)); |
| 1012 ICData::New(function, name, Object::null_array(), | 1022 __ LoadObject(ECX, ic_data); |
| 1013 Isolate::kNoDeoptId, kNumArgsChecked)); | 1023 __ LeaveFrame(); // The arguments are still on the stack. |
| 1014 __ LoadObject(ECX, ic_data); | 1024 __ jmp(&StubCode::CallNoSuchMethodFunctionLabel()); |
| 1015 __ LeaveFrame(); // The arguments are still on the stack. | 1025 // The noSuchMethod call may return to the caller, but not here. |
| 1016 __ jmp(&StubCode::CallNoSuchMethodFunctionLabel()); | 1026 __ int3(); |
| 1017 // The noSuchMethod call may return to the caller, but not here. | 1027 } else if (check_correct_named_args) { |
| 1018 __ int3(); | 1028 __ Stop("Wrong arguments"); |
| 1029 } |
| 1019 | 1030 |
| 1020 __ Bind(&all_arguments_processed); | 1031 __ Bind(&all_arguments_processed); |
| 1021 // Nullify originally passed arguments only after they have been copied and | 1032 // Nullify originally passed arguments only after they have been copied and |
| 1022 // checked, otherwise noSuchMethod would not see their original values. | 1033 // checked, otherwise noSuchMethod would not see their original values. |
| 1023 // This step can be skipped in case we decide that formal parameters are | 1034 // This step can be skipped in case we decide that formal parameters are |
| 1024 // implicitly final, since garbage collecting the unmodified value is not | 1035 // implicitly final, since garbage collecting the unmodified value is not |
| 1025 // an issue anymore. | 1036 // an issue anymore. |
| 1026 | 1037 |
| 1027 // EDX : arguments descriptor array. | 1038 // EDX : arguments descriptor array. |
| 1028 __ movl(ECX, FieldAddress(EDX, ArgumentsDescriptor::count_offset())); | 1039 __ movl(ECX, FieldAddress(EDX, ArgumentsDescriptor::count_offset())); |
| (...skipping 881 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1910 __ movups(reg, Address(ESP, 0)); | 1921 __ movups(reg, Address(ESP, 0)); |
| 1911 __ addl(ESP, Immediate(kFpuRegisterSize)); | 1922 __ addl(ESP, Immediate(kFpuRegisterSize)); |
| 1912 } | 1923 } |
| 1913 | 1924 |
| 1914 | 1925 |
| 1915 #undef __ | 1926 #undef __ |
| 1916 | 1927 |
| 1917 } // namespace dart | 1928 } // namespace dart |
| 1918 | 1929 |
| 1919 #endif // defined TARGET_ARCH_IA32 | 1930 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |