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

Side by Side Diff: vm/flow_graph_compiler_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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
75 intptr_t token_index, 75 intptr_t token_index,
76 intptr_t try_index, 76 intptr_t try_index,
77 const RuntimeEntry& entry) { 77 const RuntimeEntry& entry) {
78 __ CallRuntime(entry); 78 __ CallRuntime(entry);
79 AddCurrentDescriptor(PcDescriptors::kOther, cid, token_index, try_index); 79 AddCurrentDescriptor(PcDescriptors::kOther, cid, token_index, try_index);
80 } 80 }
81 81
82 82
83 void FlowGraphCompiler::CopyParameters() { 83 void FlowGraphCompiler::CopyParameters() {
84 const Function& function = parsed_function().function(); 84 const Function& function = parsed_function().function();
85 const bool is_implicit_native_closure =
86 function.is_native() && function.IsImplicitClosureFunction();
regis 2012/06/15 17:13:34 ditto
siva 2012/06/16 00:25:43 Done.
85 LocalScope* scope = parsed_function().node_sequence()->scope(); 87 LocalScope* scope = parsed_function().node_sequence()->scope();
86 const int num_fixed_params = function.num_fixed_parameters(); 88 const int num_fixed_params = function.num_fixed_parameters();
87 const int num_opt_params = function.num_optional_parameters(); 89 const int num_opt_params = function.num_optional_parameters();
88 ASSERT(parsed_function().first_parameter_index() == 90 ASSERT(parsed_function().first_parameter_index() ==
89 ParsedFunction::kFirstLocalSlotIndex); 91 ParsedFunction::kFirstLocalSlotIndex);
90 // Copy positional arguments. 92 // Copy positional arguments.
91 // Check that no fewer than num_fixed_params positional arguments are passed 93 // Check that no fewer than num_fixed_params positional arguments are passed
92 // in and that no more than num_params arguments are passed in. 94 // in and that no more than num_params arguments are passed in.
93 // Passed argument i at fp[1 + argc - i] 95 // Passed argument i at fp[1 + argc - i]
94 // copied to fp[ParsedFunction::kFirstLocalSlotIndex - i]. 96 // copied to fp[ParsedFunction::kFirstLocalSlotIndex - i].
95 const int num_params = num_fixed_params + num_opt_params; 97 const int num_params = num_fixed_params + num_opt_params;
96 98
97 // Total number of args is the first Smi in args descriptor array (EDX). 99 // Total number of args is the first Smi in args descriptor array (EDX).
98 __ movl(EBX, FieldAddress(EDX, Array::data_offset())); 100 __ movl(EBX, FieldAddress(EDX, Array::data_offset()));
99 // Check that num_args <= num_params. 101 // Check that num_args <= num_params.
100 Label wrong_num_arguments; 102 Label wrong_num_arguments;
101 __ cmpl(EBX, Immediate(Smi::RawValue(num_params))); 103 __ cmpl(EBX, Immediate(Smi::RawValue(num_params)));
102 __ j(GREATER, &wrong_num_arguments); 104 __ j(GREATER, &wrong_num_arguments);
103 // Number of positional args is the second Smi in descriptor array (EDX). 105 // Number of positional args is the second Smi in descriptor array (EDX).
104 __ movl(ECX, FieldAddress(EDX, Array::data_offset() + (1 * kWordSize))); 106 __ movl(ECX, FieldAddress(EDX, Array::data_offset() + (1 * kWordSize)));
105 // Check that num_pos_args >= num_fixed_params. 107 // Check that num_pos_args >= num_fixed_params.
106 __ cmpl(ECX, Immediate(Smi::RawValue(num_fixed_params))); 108 __ cmpl(ECX, Immediate(Smi::RawValue(num_fixed_params)));
107 __ j(LESS, &wrong_num_arguments); 109 __ j(LESS, &wrong_num_arguments);
108 // Since EBX and ECX are Smi, use TIMES_2 instead of TIMES_4. 110 // Since EBX and ECX are Smi, use TIMES_2 instead of TIMES_4.
109 // Let EBX point to the last passed positional argument, i.e. to 111 // Let EBX point to the last passed positional argument, i.e. to
110 // fp[1 + num_args - (num_pos_args - 1)]. 112 // fp[1 + num_args - (num_pos_args - 1)].
111 __ subl(EBX, ECX); 113 __ subl(EBX, ECX);
112 __ leal(EBX, Address(EBP, EBX, TIMES_2, 2 * kWordSize)); 114 __ leal(EBX, Address(EBP, EBX, TIMES_2, 2 * kWordSize));
115
113 // Let EDI point to the last copied positional argument, i.e. to 116 // Let EDI point to the last copied positional argument, i.e. to
114 // fp[ParsedFunction::kFirstLocalSlotIndex - (num_pos_args - 1)]. 117 // fp[ParsedFunction::kFirstLocalSlotIndex - (num_pos_args - 1)].
115 const int index = ParsedFunction::kFirstLocalSlotIndex + 1; 118 int implicit_this_param_pos = is_implicit_native_closure ? -1 : 0;
119 const int index =
120 ParsedFunction::kFirstLocalSlotIndex + 1 + implicit_this_param_pos;
121 // First copy captured receiver if function is an implicit native closure.
122 if (is_implicit_native_closure) {
123 __ movl(EAX, FieldAddress(CTX, Context::variable_offset(0)));
124 __ movl(Address(EBP, (index * kWordSize)), EAX);
125 }
116 __ leal(EDI, Address(EBP, (index * kWordSize))); 126 __ leal(EDI, Address(EBP, (index * kWordSize)));
117 __ subl(EDI, ECX); // ECX is a Smi, subtract twice for TIMES_4 scaling. 127 __ subl(EDI, ECX); // ECX is a Smi, subtract twice for TIMES_4 scaling.
118 __ subl(EDI, ECX); 128 __ subl(EDI, ECX);
119 __ SmiUntag(ECX); 129 __ SmiUntag(ECX);
120 Label loop, loop_condition; 130 Label loop, loop_condition;
121 __ jmp(&loop_condition, Assembler::kNearJump); 131 __ jmp(&loop_condition, Assembler::kNearJump);
122 // We do not use the final allocation index of the variable here, i.e. 132 // We do not use the final allocation index of the variable here, i.e.
123 // scope->VariableAt(i)->index(), because captured variables still need 133 // scope->VariableAt(i)->index(), because captured variables still need
124 // to be copied to the context that is not yet allocated. 134 // to be copied to the context that is not yet allocated.
125 const Address argument_addr(EBX, ECX, TIMES_4, 0); 135 const Address argument_addr(EBX, ECX, TIMES_4, 0);
126 const Address copy_addr(EDI, ECX, TIMES_4, 0); 136 const Address copy_addr(EDI, ECX, TIMES_4, 0);
127 __ Bind(&loop); 137 __ Bind(&loop);
128 __ movl(EAX, argument_addr); 138 __ movl(EAX, argument_addr);
129 __ movl(copy_addr, EAX); 139 __ movl(copy_addr, EAX);
130 __ Bind(&loop_condition); 140 __ Bind(&loop_condition);
131 __ decl(ECX); 141 __ decl(ECX);
132 __ j(POSITIVE, &loop, Assembler::kNearJump); 142 __ j(POSITIVE, &loop, Assembler::kNearJump);
133 143
134 // Copy or initialize optional named arguments. 144 // Copy or initialize optional named arguments.
135 ASSERT(num_opt_params > 0); // Or we would not have to copy arguments. 145 Label all_arguments_processed;
136 // Start by alphabetically sorting the names of the optional parameters.
137 LocalVariable** opt_param = new LocalVariable*[num_opt_params];
138 int* opt_param_position = new int[num_opt_params];
139 for (int pos = num_fixed_params; pos < num_params; pos++) {
140 LocalVariable* parameter = scope->VariableAt(pos);
141 const String& opt_param_name = parameter->name();
142 int i = pos - num_fixed_params;
143 while (--i >= 0) {
144 LocalVariable* param_i = opt_param[i];
145 const intptr_t result = opt_param_name.CompareTo(param_i->name());
146 ASSERT(result != 0);
147 if (result > 0) break;
148 opt_param[i + 1] = opt_param[i];
149 opt_param_position[i + 1] = opt_param_position[i];
150 }
151 opt_param[i + 1] = parameter;
152 opt_param_position[i + 1] = pos;
153 }
154 // Generate code handling each optional parameter in alphabetical order.
155 // Total number of args is the first Smi in args descriptor array (EDX).
156 __ movl(EBX, FieldAddress(EDX, Array::data_offset()));
157 // Number of positional args is the second Smi in descriptor array (EDX).
158 __ movl(ECX, FieldAddress(EDX, Array::data_offset() + (1 * kWordSize)));
159 __ SmiUntag(ECX);
160 // Let EBX point to the first passed argument, i.e. to fp[1 + argc - 0].
161 __ leal(EBX, Address(EBP, EBX, TIMES_2, kWordSize)); // EBX is Smi.
162 // Let EDI point to the name/pos pair of the first named argument.
163 __ leal(EDI, FieldAddress(EDX, Array::data_offset() + (2 * kWordSize)));
164 for (int i = 0; i < num_opt_params; i++) {
165 // Handle this optional parameter only if k or fewer positional arguments
166 // have been passed, where k is the position of this optional parameter in
167 // the formal parameter list.
168 Label load_default_value, assign_optional_parameter, next_parameter;
169 const int param_pos = opt_param_position[i];
170 __ cmpl(ECX, Immediate(param_pos));
171 __ j(GREATER, &next_parameter, Assembler::kNearJump);
172 // Check if this named parameter was passed in.
173 __ movl(EAX, Address(EDI, 0)); // Load EAX with the name of the argument.
174 __ CompareObject(EAX, opt_param[i]->name());
175 __ j(NOT_EQUAL, &load_default_value, Assembler::kNearJump);
176 // Load EAX with passed-in argument at provided arg_pos, i.e. at
177 // fp[1 + argc - arg_pos].
178 __ movl(EAX, Address(EDI, kWordSize)); // EAX is arg_pos as Smi.
179 __ addl(EDI, Immediate(2 * kWordSize)); // Point to next name/pos pair.
180 __ negl(EAX);
181 Address argument_addr(EBX, EAX, TIMES_2, 0); // EAX is a negative Smi.
182 __ movl(EAX, argument_addr);
183 __ jmp(&assign_optional_parameter, Assembler::kNearJump);
184 __ Bind(&load_default_value);
185 // Load EAX with default argument at pos.
186 const Object& value = Object::ZoneHandle(
187 parsed_function().default_parameter_values().At(
188 param_pos - num_fixed_params));
189 __ LoadObject(EAX, value);
190 __ Bind(&assign_optional_parameter);
191 // Assign EAX to fp[ParsedFunction::kFirstLocalSlotIndex - param_pos].
192 // We do not use the final allocation index of the variable here, i.e.
193 // scope->VariableAt(i)->index(), because captured variables still need
194 // to be copied to the context that is not yet allocated.
195 const Address param_addr(
196 EBP, (ParsedFunction::kFirstLocalSlotIndex - param_pos) * kWordSize);
197 __ movl(param_addr, EAX);
198 __ Bind(&next_parameter);
199 }
200 delete[] opt_param;
201 delete[] opt_param_position;
202 // Check that EDI now points to the null terminator in the array descriptor.
203 const Immediate raw_null = 146 const Immediate raw_null =
204 Immediate(reinterpret_cast<intptr_t>(Object::null())); 147 Immediate(reinterpret_cast<intptr_t>(Object::null()));
205 Label all_arguments_processed; 148 if (num_opt_params > 0) {
206 __ cmpl(Address(EDI, 0), raw_null); 149 // Start by alphabetically sorting the names of the optional parameters.
207 __ j(EQUAL, &all_arguments_processed, Assembler::kNearJump); 150 LocalVariable** opt_param = new LocalVariable*[num_opt_params];
151 int* opt_param_position = new int[num_opt_params];
152 for (int pos = num_fixed_params; pos < num_params; pos++) {
153 LocalVariable* parameter = scope->VariableAt(pos);
154 const String& opt_param_name = parameter->name();
155 int i = pos - num_fixed_params;
156 while (--i >= 0) {
157 LocalVariable* param_i = opt_param[i];
158 const intptr_t result = opt_param_name.CompareTo(param_i->name());
159 ASSERT(result != 0);
160 if (result > 0) break;
161 opt_param[i + 1] = opt_param[i];
162 opt_param_position[i + 1] = opt_param_position[i];
163 }
164 opt_param[i + 1] = parameter;
165 opt_param_position[i + 1] = pos;
166 }
167 // Generate code handling each optional parameter in alphabetical order.
168 // Total number of args is the first Smi in args descriptor array (EDX).
169 __ movl(EBX, FieldAddress(EDX, Array::data_offset()));
170 // Number of positional args is the second Smi in descriptor array (EDX).
171 __ movl(ECX, FieldAddress(EDX, Array::data_offset() + (1 * kWordSize)));
172 __ SmiUntag(ECX);
173 // Let EBX point to the first passed argument, i.e. to fp[1 + argc - 0].
174 __ leal(EBX, Address(EBP, EBX, TIMES_2, kWordSize)); // EBX is Smi.
175 // Let EDI point to the name/pos pair of the first named argument.
176 __ leal(EDI, FieldAddress(EDX, Array::data_offset() + (2 * kWordSize)));
177 for (int i = 0; i < num_opt_params; i++) {
178 // Handle this optional parameter only if k or fewer positional arguments
179 // have been passed, where k is the position of this optional parameter in
180 // the formal parameter list.
181 Label load_default_value, assign_optional_parameter, next_parameter;
182 const int param_pos = opt_param_position[i];
183 __ cmpl(ECX, Immediate(param_pos));
184 __ j(GREATER, &next_parameter, Assembler::kNearJump);
185 // Check if this named parameter was passed in.
186 __ movl(EAX, Address(EDI, 0)); // Load EAX with the name of the argument.
187 __ CompareObject(EAX, opt_param[i]->name());
188 __ j(NOT_EQUAL, &load_default_value, Assembler::kNearJump);
189 // Load EAX with passed-in argument at provided arg_pos, i.e. at
190 // fp[1 + argc - arg_pos].
191 __ movl(EAX, Address(EDI, kWordSize)); // EAX is arg_pos as Smi.
192 __ addl(EDI, Immediate(2 * kWordSize)); // Point to next name/pos pair.
193 __ negl(EAX);
194 Address argument_addr(EBX, EAX, TIMES_2, 0); // EAX is a negative Smi.
195 __ movl(EAX, argument_addr);
196 __ jmp(&assign_optional_parameter, Assembler::kNearJump);
197 __ Bind(&load_default_value);
198 // Load EAX with default argument at pos.
199 const Object& value = Object::ZoneHandle(
200 parsed_function().default_parameter_values().At(
201 param_pos - num_fixed_params));
202 __ LoadObject(EAX, value);
203 __ Bind(&assign_optional_parameter);
204 // Assign EAX to fp[ParsedFunction::kFirstLocalSlotIndex - param_pos].
205 // We do not use the final allocation index of the variable here, i.e.
206 // scope->VariableAt(i)->index(), because captured variables still need
207 // to be copied to the context that is not yet allocated.
208 intptr_t computed_param_pos = (ParsedFunction::kFirstLocalSlotIndex -
209 param_pos + implicit_this_param_pos);
210 const Address param_addr(EBP, (computed_param_pos * kWordSize));
211 __ movl(param_addr, EAX);
212 __ Bind(&next_parameter);
213 }
214 delete[] opt_param;
215 delete[] opt_param_position;
216 // Check that EDI now points to the null terminator in the array descriptor.
217 __ cmpl(Address(EDI, 0), raw_null);
218 __ j(EQUAL, &all_arguments_processed, Assembler::kNearJump);
219 } else {
220 ASSERT(is_implicit_native_closure);
221 __ jmp(&all_arguments_processed, Assembler::kNearJump);
222 }
208 223
209 __ Bind(&wrong_num_arguments); 224 __ Bind(&wrong_num_arguments);
210 if (StackSize() != 0) { 225 if (StackSize() != 0) {
211 // We need to unwind the space we reserved for locals and copied parameters. 226 // We need to unwind the space we reserved for locals and copied parameters.
212 // The NoSuchMethodFunction stub does not expect to see that area on the 227 // The NoSuchMethodFunction stub does not expect to see that area on the
213 // stack. 228 // stack.
214 __ addl(ESP, Immediate(StackSize() * kWordSize)); 229 __ addl(ESP, Immediate(StackSize() * kWordSize));
215 } 230 }
216 if (function.IsClosureFunction()) { 231 if (function.IsClosureFunction()) {
217 GenerateCallRuntime(AstNode::kNoId, 232 GenerateCallRuntime(AstNode::kNoId,
(...skipping 788 matching lines...) Expand 10 before | Expand all | Expand 10 after
1006 __ cvtsi2sd(result, temp); 1021 __ cvtsi2sd(result, temp);
1007 __ Bind(&done); 1022 __ Bind(&done);
1008 } 1023 }
1009 1024
1010 1025
1011 #undef __ 1026 #undef __
1012 1027
1013 } // namespace dart 1028 } // namespace dart
1014 1029
1015 #endif // defined TARGET_ARCH_IA32 1030 #endif // defined TARGET_ARCH_IA32
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698