| 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_ARM. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM. |
| 6 #if defined(TARGET_ARCH_ARM) | 6 #if defined(TARGET_ARCH_ARM) |
| 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 861 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 872 const Address copy_addr(R6, R8, LSL, 2); | 872 const Address copy_addr(R6, R8, LSL, 2); |
| 873 __ Bind(&loop); | 873 __ Bind(&loop); |
| 874 __ ldr(IP, argument_addr); | 874 __ ldr(IP, argument_addr); |
| 875 __ str(IP, copy_addr); | 875 __ str(IP, copy_addr); |
| 876 __ Bind(&loop_condition); | 876 __ Bind(&loop_condition); |
| 877 __ subs(R8, R8, ShifterOperand(1)); | 877 __ subs(R8, R8, ShifterOperand(1)); |
| 878 __ b(&loop, PL); | 878 __ b(&loop, PL); |
| 879 | 879 |
| 880 // Copy or initialize optional named arguments. | 880 // Copy or initialize optional named arguments. |
| 881 Label all_arguments_processed; | 881 Label all_arguments_processed; |
| 882 #ifdef DEBUG |
| 883 const bool check_correct_named_args = true; |
| 884 #else |
| 885 const bool check_correct_named_args = function.IsClosureFunction(); |
| 886 #endif |
| 882 if (num_opt_named_params > 0) { | 887 if (num_opt_named_params > 0) { |
| 883 // Start by alphabetically sorting the names of the optional parameters. | 888 // Start by alphabetically sorting the names of the optional parameters. |
| 884 LocalVariable** opt_param = new LocalVariable*[num_opt_named_params]; | 889 LocalVariable** opt_param = new LocalVariable*[num_opt_named_params]; |
| 885 int* opt_param_position = new int[num_opt_named_params]; | 890 int* opt_param_position = new int[num_opt_named_params]; |
| 886 for (int pos = num_fixed_params; pos < num_params; pos++) { | 891 for (int pos = num_fixed_params; pos < num_params; pos++) { |
| 887 LocalVariable* parameter = scope->VariableAt(pos); | 892 LocalVariable* parameter = scope->VariableAt(pos); |
| 888 const String& opt_param_name = parameter->name(); | 893 const String& opt_param_name = parameter->name(); |
| 889 int i = pos - num_fixed_params; | 894 int i = pos - num_fixed_params; |
| 890 while (--i >= 0) { | 895 while (--i >= 0) { |
| 891 LocalVariable* param_i = opt_param[i]; | 896 LocalVariable* param_i = opt_param[i]; |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 939 // Assign R5 to fp[kFirstLocalSlotFromFp - param_pos]. | 944 // Assign R5 to fp[kFirstLocalSlotFromFp - param_pos]. |
| 940 // We do not use the final allocation index of the variable here, i.e. | 945 // We do not use the final allocation index of the variable here, i.e. |
| 941 // scope->VariableAt(i)->index(), because captured variables still need | 946 // scope->VariableAt(i)->index(), because captured variables still need |
| 942 // to be copied to the context that is not yet allocated. | 947 // to be copied to the context that is not yet allocated. |
| 943 const intptr_t computed_param_pos = kFirstLocalSlotFromFp - param_pos; | 948 const intptr_t computed_param_pos = kFirstLocalSlotFromFp - param_pos; |
| 944 const Address param_addr(FP, computed_param_pos * kWordSize); | 949 const Address param_addr(FP, computed_param_pos * kWordSize); |
| 945 __ str(R5, param_addr); | 950 __ str(R5, param_addr); |
| 946 } | 951 } |
| 947 delete[] opt_param; | 952 delete[] opt_param; |
| 948 delete[] opt_param_position; | 953 delete[] opt_param_position; |
| 949 // Check that R6 now points to the null terminator in the array descriptor. | 954 if (check_correct_named_args) { |
| 950 __ ldr(R5, Address(R6, 0)); | 955 // Check that R6 now points to the null terminator in the arguments |
| 951 __ CompareImmediate(R5, reinterpret_cast<int32_t>(Object::null())); | 956 // descriptor. |
| 952 __ b(&all_arguments_processed, EQ); | 957 __ ldr(R5, Address(R6, 0)); |
| 958 __ CompareImmediate(R5, reinterpret_cast<int32_t>(Object::null())); |
| 959 __ b(&all_arguments_processed, EQ); |
| 960 } |
| 953 } else { | 961 } else { |
| 954 ASSERT(num_opt_pos_params > 0); | 962 ASSERT(num_opt_pos_params > 0); |
| 955 __ ldr(R8, | 963 __ ldr(R8, |
| 956 FieldAddress(R4, ArgumentsDescriptor::positional_count_offset())); | 964 FieldAddress(R4, ArgumentsDescriptor::positional_count_offset())); |
| 957 __ SmiUntag(R8); | 965 __ SmiUntag(R8); |
| 958 for (int i = 0; i < num_opt_pos_params; i++) { | 966 for (int i = 0; i < num_opt_pos_params; i++) { |
| 959 Label next_parameter; | 967 Label next_parameter; |
| 960 // Handle this optional positional parameter only if k or fewer positional | 968 // Handle this optional positional parameter only if k or fewer positional |
| 961 // arguments have been passed, where k is param_pos, the position of this | 969 // arguments have been passed, where k is param_pos, the position of this |
| 962 // optional parameter in the formal parameter list. | 970 // optional parameter in the formal parameter list. |
| 963 const int param_pos = num_fixed_params + i; | 971 const int param_pos = num_fixed_params + i; |
| 964 __ CompareImmediate(R8, param_pos); | 972 __ CompareImmediate(R8, param_pos); |
| 965 __ b(&next_parameter, GT); | 973 __ b(&next_parameter, GT); |
| 966 // Load R5 with default argument. | 974 // Load R5 with default argument. |
| 967 const Object& value = Object::ZoneHandle( | 975 const Object& value = Object::ZoneHandle( |
| 968 parsed_function().default_parameter_values().At(i)); | 976 parsed_function().default_parameter_values().At(i)); |
| 969 __ LoadObject(R5, value); | 977 __ LoadObject(R5, value); |
| 970 // Assign R5 to fp[kFirstLocalSlotFromFp - param_pos]. | 978 // Assign R5 to fp[kFirstLocalSlotFromFp - param_pos]. |
| 971 // We do not use the final allocation index of the variable here, i.e. | 979 // We do not use the final allocation index of the variable here, i.e. |
| 972 // scope->VariableAt(i)->index(), because captured variables still need | 980 // scope->VariableAt(i)->index(), because captured variables still need |
| 973 // to be copied to the context that is not yet allocated. | 981 // to be copied to the context that is not yet allocated. |
| 974 const intptr_t computed_param_pos = kFirstLocalSlotFromFp - param_pos; | 982 const intptr_t computed_param_pos = kFirstLocalSlotFromFp - param_pos; |
| 975 const Address param_addr(FP, computed_param_pos * kWordSize); | 983 const Address param_addr(FP, computed_param_pos * kWordSize); |
| 976 __ str(R5, param_addr); | 984 __ str(R5, param_addr); |
| 977 __ Bind(&next_parameter); | 985 __ Bind(&next_parameter); |
| 978 } | 986 } |
| 979 __ ldr(R7, FieldAddress(R4, ArgumentsDescriptor::count_offset())); | 987 if (check_correct_named_args) { |
| 980 __ SmiUntag(R7); | 988 __ ldr(R7, FieldAddress(R4, ArgumentsDescriptor::count_offset())); |
| 981 // Check that R8 equals R7, i.e. no named arguments passed. | 989 __ SmiUntag(R7); |
| 982 __ cmp(R8, ShifterOperand(R7)); | 990 // Check that R8 equals R7, i.e. no named arguments passed. |
| 983 __ b(&all_arguments_processed, EQ); | 991 __ cmp(R8, ShifterOperand(R7)); |
| 992 __ b(&all_arguments_processed, EQ); |
| 993 } |
| 984 } | 994 } |
| 985 | 995 |
| 986 __ Bind(&wrong_num_arguments); | 996 __ Bind(&wrong_num_arguments); |
| 987 // Invoke noSuchMethod function passing the original name of the function. | 997 if (function.IsClosureFunction()) { |
| 988 // If the function is a closure function, use "call" as the original name. | 998 // Invoke noSuchMethod function passing "call" as the original name. |
| 989 const String& name = String::Handle( | 999 const int kNumArgsChecked = 1; |
| 990 function.IsClosureFunction() ? Symbols::Call().raw() : function.name()); | 1000 const ICData& ic_data = ICData::ZoneHandle( |
| 991 const int kNumArgsChecked = 1; | 1001 ICData::New(function, Symbols::Call(), Object::null_array(), |
| 992 const ICData& ic_data = ICData::ZoneHandle( | 1002 Isolate::kNoDeoptId, kNumArgsChecked)); |
| 993 ICData::New(function, name, Object::null_array(), | 1003 __ LoadObject(R5, ic_data); |
| 994 Isolate::kNoDeoptId, kNumArgsChecked)); | 1004 __ LeaveDartFrame(); // The arguments are still on the stack. |
| 995 __ LoadObject(R5, ic_data); | 1005 __ Branch(&StubCode::CallNoSuchMethodFunctionLabel()); |
| 996 __ LeaveDartFrame(); // The arguments are still on the stack. | 1006 // The noSuchMethod call may return to the caller, but not here. |
| 997 __ Branch(&StubCode::CallNoSuchMethodFunctionLabel()); | 1007 __ bkpt(0); |
| 998 // The noSuchMethod call may return to the caller, but not here. | 1008 } else if (check_correct_named_args) { |
| 999 __ bkpt(0); | 1009 __ Stop("Wrong arguments"); |
| 1010 } |
| 1000 | 1011 |
| 1001 __ Bind(&all_arguments_processed); | 1012 __ Bind(&all_arguments_processed); |
| 1002 // Nullify originally passed arguments only after they have been copied and | 1013 // Nullify originally passed arguments only after they have been copied and |
| 1003 // checked, otherwise noSuchMethod would not see their original values. | 1014 // checked, otherwise noSuchMethod would not see their original values. |
| 1004 // This step can be skipped in case we decide that formal parameters are | 1015 // This step can be skipped in case we decide that formal parameters are |
| 1005 // implicitly final, since garbage collecting the unmodified value is not | 1016 // implicitly final, since garbage collecting the unmodified value is not |
| 1006 // an issue anymore. | 1017 // an issue anymore. |
| 1007 | 1018 |
| 1008 // R4 : arguments descriptor array. | 1019 // R4 : arguments descriptor array. |
| 1009 __ ldr(R8, FieldAddress(R4, ArgumentsDescriptor::count_offset())); | 1020 __ ldr(R8, FieldAddress(R4, ArgumentsDescriptor::count_offset())); |
| (...skipping 858 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1868 DRegister dreg = EvenDRegisterOf(reg); | 1879 DRegister dreg = EvenDRegisterOf(reg); |
| 1869 __ vldrd(dreg, Address(SP, kDoubleSize, Address::PostIndex)); | 1880 __ vldrd(dreg, Address(SP, kDoubleSize, Address::PostIndex)); |
| 1870 } | 1881 } |
| 1871 | 1882 |
| 1872 | 1883 |
| 1873 #undef __ | 1884 #undef __ |
| 1874 | 1885 |
| 1875 } // namespace dart | 1886 } // namespace dart |
| 1876 | 1887 |
| 1877 #endif // defined TARGET_ARCH_ARM | 1888 #endif // defined TARGET_ARCH_ARM |
| OLD | NEW |