Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(145)

Unified Diff: vm/code_generator_ia32.cc

Issue 10535180: Allow implicit 'close your eyes' of native methods. This will hopefully fix issue 3466. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/runtime/
Patch Set: Created 8 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « vm/ast.h ('k') | vm/code_generator_test.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: vm/code_generator_ia32.cc
===================================================================
--- vm/code_generator_ia32.cc (revision 8752)
+++ vm/code_generator_ia32.cc (working copy)
@@ -373,6 +373,8 @@
const Immediate raw_null =
Immediate(reinterpret_cast<intptr_t>(Object::null()));
const Function& function = parsed_function_.function();
+ const bool is_instance_native_closure =
+ function.is_native() && function.IsImplicitInstanceClosureFunction();
// 1. Compute the frame size and enter the frame (reserving local space
// for copied incoming and default arguments and stack-allocated local
@@ -441,6 +443,7 @@
// Check that num_pos_args >= num_fixed_params.
__ cmpl(ECX, Immediate(Smi::RawValue(num_fixed_params)));
__ j(LESS, &wrong_num_arguments);
+
// Since EBX and ECX are Smi, use TIMES_2 instead of TIMES_4.
// Let EBX point to the last passed positional argument, i.e. to
// fp[1 + num_args - (num_pos_args - 1)].
@@ -448,7 +451,14 @@
__ leal(EBX, Address(EBP, EBX, TIMES_2, 2 * kWordSize));
// Let EDI point to the last copied positional argument, i.e. to
// fp[ParsedFunction::kFirstLocalSlotIndex - (num_pos_args - 1)].
- const int index = ParsedFunction::kFirstLocalSlotIndex + 1;
+ int implicit_this_param_pos = is_instance_native_closure ? -1 : 0;
+ const int index =
+ ParsedFunction::kFirstLocalSlotIndex + 1 + implicit_this_param_pos;
+ // First copy captured receiver if function is an implicit native closure.
+ if (is_instance_native_closure) {
+ __ movl(EAX, FieldAddress(CTX, Context::variable_offset(0)));
+ __ movl(Address(EBP, (index * kWordSize)), EAX);
+ }
__ leal(EDI, Address(EBP, (index * kWordSize)));
__ subl(EDI, ECX); // ECX is a Smi, subtract twice for TIMES_4 scaling.
__ subl(EDI, ECX);
@@ -468,77 +478,82 @@
__ j(POSITIVE, &loop, Assembler::kNearJump);
// Copy or initialize optional named arguments.
- ASSERT(num_opt_params > 0); // Or we would not have to copy arguments.
- // Start by alphabetically sorting the names of the optional parameters.
- LocalVariable** opt_param = new LocalVariable*[num_opt_params];
- int* opt_param_position = new int[num_opt_params];
- for (int pos = num_fixed_params; pos < num_params; pos++) {
- LocalVariable* parameter = scope->VariableAt(pos);
- const String& opt_param_name = parameter->name();
- int i = pos - num_fixed_params;
- while (--i >= 0) {
- LocalVariable* param_i = opt_param[i];
- const intptr_t result = opt_param_name.CompareTo(param_i->name());
- ASSERT(result != 0);
- if (result > 0) break;
- opt_param[i + 1] = opt_param[i];
- opt_param_position[i + 1] = opt_param_position[i];
+ Label all_arguments_processed;
+ if (num_opt_params > 0) {
+ // Start by alphabetically sorting the names of the optional parameters.
+ LocalVariable** opt_param = new LocalVariable*[num_opt_params];
+ int* opt_param_position = new int[num_opt_params];
+ for (int pos = num_fixed_params; pos < num_params; pos++) {
+ LocalVariable* parameter = scope->VariableAt(pos);
+ const String& opt_param_name = parameter->name();
+ int i = pos - num_fixed_params;
+ while (--i >= 0) {
+ LocalVariable* param_i = opt_param[i];
+ const intptr_t result = opt_param_name.CompareTo(param_i->name());
+ ASSERT(result != 0);
+ if (result > 0) break;
+ opt_param[i + 1] = opt_param[i];
+ opt_param_position[i + 1] = opt_param_position[i];
+ }
+ opt_param[i + 1] = parameter;
+ opt_param_position[i + 1] = pos;
}
- opt_param[i + 1] = parameter;
- opt_param_position[i + 1] = pos;
+ // Generate code handling each optional parameter in alphabetical order.
+ // Total number of args is the first Smi in args descriptor array (EDX).
+ __ movl(EBX, FieldAddress(EDX, Array::data_offset()));
+ // Number of positional args is the second Smi in descriptor array (EDX).
+ __ movl(ECX, FieldAddress(EDX, Array::data_offset() + (1 * kWordSize)));
+ __ SmiUntag(ECX);
+ // Let EBX point to the first passed argument, i.e. to fp[1 + argc - 0].
+ __ leal(EBX, Address(EBP, EBX, TIMES_2, kWordSize));
+ // Let EDI point to the name/pos pair of the first named argument.
+ __ leal(EDI, FieldAddress(EDX, Array::data_offset() + (2 * kWordSize)));
+ for (int i = 0; i < num_opt_params; i++) {
+ // Handle this optional parameter only if k or fewer positional args
+ // have been passed, where k is the position of this optional parameter
+ // in the formal parameter list.
+ Label load_default_value, assign_optional_parameter, next_parameter;
+ const int param_pos = opt_param_position[i];
+ __ cmpl(ECX, Immediate(param_pos));
+ __ j(GREATER, &next_parameter, Assembler::kNearJump);
+ // Check if this named parameter was passed in.
+ __ movl(EAX, Address(EDI, 0)); // Load EAX with the name of the arg.
+ __ CompareObject(EAX, opt_param[i]->name());
+ __ j(NOT_EQUAL, &load_default_value, Assembler::kNearJump);
+ // Load EAX with passed-in argument at provided arg_pos, i.e. at
+ // fp[1 + argc - arg_pos].
+ __ movl(EAX, Address(EDI, kWordSize)); // EAX is arg_pos as Smi.
+ __ addl(EDI, Immediate(2 * kWordSize)); // Point to next name/pos pair.
+ __ negl(EAX);
+ Address argument_addr(EBX, EAX, TIMES_2, 0); // EAX is a negative Smi.
+ __ movl(EAX, argument_addr);
+ __ jmp(&assign_optional_parameter, Assembler::kNearJump);
+ __ Bind(&load_default_value);
+ // Load EAX with default argument at pos.
+ const Object& value = Object::ZoneHandle(
+ parsed_function_.default_parameter_values().At(
+ param_pos - num_fixed_params));
+ __ LoadObject(EAX, value);
+ __ Bind(&assign_optional_parameter);
+ // Assign EAX to fp[ParsedFunction::kFirstLocalSlotIndex - param_pos].
+ // We do not use the final allocation index of the variable here, i.e.
+ // scope->VariableAt(i)->index(), because captured variables still need
+ // to be copied to the context that is not yet allocated.
+ intptr_t computed_param_pos = (ParsedFunction::kFirstLocalSlotIndex -
+ param_pos + implicit_this_param_pos);
+ const Address param_addr(EBP, (computed_param_pos * kWordSize));
+ __ movl(param_addr, EAX);
+ __ Bind(&next_parameter);
+ }
+ delete[] opt_param;
+ delete[] opt_param_position;
+ // Check that EDI now points to null terminator in the array descriptor.
+ __ cmpl(Address(EDI, 0), raw_null);
+ __ j(EQUAL, &all_arguments_processed, Assembler::kNearJump);
+ } else {
+ ASSERT(is_instance_native_closure);
+ __ jmp(&all_arguments_processed, Assembler::kNearJump);
}
- // Generate code handling each optional parameter in alphabetical order.
- // Total number of args is the first Smi in args descriptor array (EDX).
- __ movl(EBX, FieldAddress(EDX, Array::data_offset()));
- // Number of positional args is the second Smi in descriptor array (EDX).
- __ movl(ECX, FieldAddress(EDX, Array::data_offset() + (1 * kWordSize)));
- __ SmiUntag(ECX);
- // Let EBX point to the first passed argument, i.e. to fp[1 + argc - 0].
- __ leal(EBX, Address(EBP, EBX, TIMES_2, kWordSize));
- // Let EDI point to the name/pos pair of the first named argument.
- __ leal(EDI, FieldAddress(EDX, Array::data_offset() + (2 * kWordSize)));
- for (int i = 0; i < num_opt_params; i++) {
- // Handle this optional parameter only if k or fewer positional arguments
- // have been passed, where k is the position of this optional parameter in
- // the formal parameter list.
- Label load_default_value, assign_optional_parameter, next_parameter;
- const int param_pos = opt_param_position[i];
- __ cmpl(ECX, Immediate(param_pos));
- __ j(GREATER, &next_parameter, Assembler::kNearJump);
- // Check if this named parameter was passed in.
- __ movl(EAX, Address(EDI, 0)); // Load EAX with the name of the argument.
- __ CompareObject(EAX, opt_param[i]->name());
- __ j(NOT_EQUAL, &load_default_value, Assembler::kNearJump);
- // Load EAX with passed-in argument at provided arg_pos, i.e. at
- // fp[1 + argc - arg_pos].
- __ movl(EAX, Address(EDI, kWordSize)); // EAX is arg_pos as Smi.
- __ addl(EDI, Immediate(2 * kWordSize)); // Point to next name/pos pair.
- __ negl(EAX);
- Address argument_addr(EBX, EAX, TIMES_2, 0); // EAX is a negative Smi.
- __ movl(EAX, argument_addr);
- __ jmp(&assign_optional_parameter, Assembler::kNearJump);
- __ Bind(&load_default_value);
- // Load EAX with default argument at pos.
- const Object& value = Object::ZoneHandle(
- parsed_function_.default_parameter_values().At(
- param_pos - num_fixed_params));
- __ LoadObject(EAX, value);
- __ Bind(&assign_optional_parameter);
- // Assign EAX to fp[ParsedFunction::kFirstLocalSlotIndex - param_pos].
- // We do not use the final allocation index of the variable here, i.e.
- // scope->VariableAt(i)->index(), because captured variables still need
- // to be copied to the context that is not yet allocated.
- const Address param_addr(
- EBP, (ParsedFunction::kFirstLocalSlotIndex - param_pos) * kWordSize);
- __ movl(param_addr, EAX);
- __ Bind(&next_parameter);
- }
- delete[] opt_param;
- delete[] opt_param_position;
- // Check that EDI now points to the null terminator in the array descriptor.
- Label all_arguments_processed;
- __ cmpl(Address(EDI, 0), raw_null);
- __ j(EQUAL, &all_arguments_processed, Assembler::kNearJump);
__ Bind(&wrong_num_arguments);
if (locals_space_size() != 0) {
@@ -2767,17 +2782,22 @@
void CodeGenerator::VisitNativeBodyNode(NativeBodyNode* node) {
+ intptr_t argument_count = node->argument_count();
+ if (node->is_native_instance_closure()) {
+ argument_count += 1;
+ }
+
// Push the result place holder initialized to NULL.
__ PushObject(Object::ZoneHandle());
// Pass a pointer to the first argument in EAX.
- if (!node->has_optional_parameters()) {
- __ leal(EAX, Address(EBP, (1 + node->argument_count()) * kWordSize));
+ if (!node->has_optional_parameters() && !node->is_native_instance_closure()) {
+ __ leal(EAX, Address(EBP, (1 + argument_count) * kWordSize));
} else {
__ leal(EAX,
Address(EBP, ParsedFunction::kFirstLocalSlotIndex * kWordSize));
}
__ movl(ECX, Immediate(reinterpret_cast<uword>(node->native_c_function())));
- __ movl(EDX, Immediate(node->argument_count()));
+ __ movl(EDX, Immediate(argument_count));
GenerateCall(node->token_index(),
&StubCode::CallNativeCFunctionLabel(),
PcDescriptors::kOther);
« no previous file with comments | « vm/ast.h ('k') | vm/code_generator_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698