| Index: runtime/vm/flow_graph_compiler_x64.cc
|
| ===================================================================
|
| --- runtime/vm/flow_graph_compiler_x64.cc (revision 25039)
|
| +++ runtime/vm/flow_graph_compiler_x64.cc (working copy)
|
| @@ -893,6 +893,11 @@
|
| const Immediate& raw_null =
|
| Immediate(reinterpret_cast<intptr_t>(Object::null()));
|
| Label all_arguments_processed;
|
| +#ifdef DEBUG
|
| + const bool check_correct_named_args = true;
|
| +#else
|
| + const bool check_correct_named_args = function.IsClosureFunction();
|
| +#endif
|
| if (num_opt_named_params > 0) {
|
| // Start by alphabetically sorting the names of the optional parameters.
|
| LocalVariable** opt_param = new LocalVariable*[num_opt_named_params];
|
| @@ -960,9 +965,12 @@
|
| }
|
| delete[] opt_param;
|
| delete[] opt_param_position;
|
| - // Check that RDI now points to the null terminator in the array descriptor.
|
| - __ cmpq(Address(RDI, 0), raw_null);
|
| - __ j(EQUAL, &all_arguments_processed, Assembler::kNearJump);
|
| + if (check_correct_named_args) {
|
| + // Check that RDI now points to the null terminator in the arguments
|
| + // descriptor.
|
| + __ cmpq(Address(RDI, 0), raw_null);
|
| + __ j(EQUAL, &all_arguments_processed, Assembler::kNearJump);
|
| + }
|
| } else {
|
| ASSERT(num_opt_pos_params > 0);
|
| __ movq(RCX,
|
| @@ -989,27 +997,30 @@
|
| __ movq(param_addr, RAX);
|
| __ Bind(&next_parameter);
|
| }
|
| - __ movq(RBX, FieldAddress(R10, ArgumentsDescriptor::count_offset()));
|
| - __ SmiUntag(RBX);
|
| - // Check that RCX equals RBX, i.e. no named arguments passed.
|
| - __ cmpq(RCX, RBX);
|
| - __ j(EQUAL, &all_arguments_processed, Assembler::kNearJump);
|
| + if (check_correct_named_args) {
|
| + __ movq(RBX, FieldAddress(R10, ArgumentsDescriptor::count_offset()));
|
| + __ SmiUntag(RBX);
|
| + // Check that RCX equals RBX, i.e. no named arguments passed.
|
| + __ cmpq(RCX, RBX);
|
| + __ j(EQUAL, &all_arguments_processed, Assembler::kNearJump);
|
| + }
|
| }
|
|
|
| __ Bind(&wrong_num_arguments);
|
| - // Invoke noSuchMethod function passing the original name of the function.
|
| - // If the function is a closure function, use "call" as the original name.
|
| - const String& name = String::Handle(
|
| - function.IsClosureFunction() ? Symbols::Call().raw() : function.name());
|
| - const int kNumArgsChecked = 1;
|
| - const ICData& ic_data = ICData::ZoneHandle(
|
| - ICData::New(function, name, Object::null_array(),
|
| - Isolate::kNoDeoptId, kNumArgsChecked));
|
| - __ LoadObject(RBX, ic_data);
|
| - __ LeaveFrame(); // The arguments are still on the stack.
|
| - __ jmp(&StubCode::CallNoSuchMethodFunctionLabel());
|
| - // The noSuchMethod call may return to the caller, but not here.
|
| - __ int3();
|
| + if (function.IsClosureFunction()) {
|
| + // Invoke noSuchMethod function passing "call" as the original name.
|
| + const int kNumArgsChecked = 1;
|
| + const ICData& ic_data = ICData::ZoneHandle(
|
| + ICData::New(function, Symbols::Call(), Object::null_array(),
|
| + Isolate::kNoDeoptId, kNumArgsChecked));
|
| + __ LoadObject(RBX, ic_data);
|
| + __ LeaveFrame(); // The arguments are still on the stack.
|
| + __ jmp(&StubCode::CallNoSuchMethodFunctionLabel());
|
| + // The noSuchMethod call may return to the caller, but not here.
|
| + __ int3();
|
| + } else if (check_correct_named_args) {
|
| + __ Stop("Wrong arguments");
|
| + }
|
|
|
| __ Bind(&all_arguments_processed);
|
| // Nullify originally passed arguments only after they have been copied and
|
|
|