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

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
« no previous file with comments | « vm/dart_api_impl_test.cc ('k') | vm/flow_graph_compiler_x64.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
99 intptr_t token_index, 99 intptr_t token_index,
100 intptr_t try_index, 100 intptr_t try_index,
101 const RuntimeEntry& entry) { 101 const RuntimeEntry& entry) {
102 __ CallRuntime(entry); 102 __ CallRuntime(entry);
103 AddCurrentDescriptor(PcDescriptors::kOther, cid, token_index, try_index); 103 AddCurrentDescriptor(PcDescriptors::kOther, cid, token_index, try_index);
104 } 104 }
105 105
106 106
107 void FlowGraphCompiler::CopyParameters() { 107 void FlowGraphCompiler::CopyParameters() {
108 const Function& function = parsed_function().function(); 108 const Function& function = parsed_function().function();
109 const bool is_native_instance_closure =
110 function.is_native() && function.IsImplicitInstanceClosureFunction();
109 LocalScope* scope = parsed_function().node_sequence()->scope(); 111 LocalScope* scope = parsed_function().node_sequence()->scope();
110 const int num_fixed_params = function.num_fixed_parameters(); 112 const int num_fixed_params = function.num_fixed_parameters();
111 const int num_opt_params = function.num_optional_parameters(); 113 const int num_opt_params = function.num_optional_parameters();
112 ASSERT(parsed_function().first_parameter_index() == 114 ASSERT(parsed_function().first_parameter_index() ==
113 ParsedFunction::kFirstLocalSlotIndex); 115 ParsedFunction::kFirstLocalSlotIndex);
114 // Copy positional arguments. 116 // Copy positional arguments.
115 // Check that no fewer than num_fixed_params positional arguments are passed 117 // Check that no fewer than num_fixed_params positional arguments are passed
116 // in and that no more than num_params arguments are passed in. 118 // in and that no more than num_params arguments are passed in.
117 // Passed argument i at fp[1 + argc - i] 119 // Passed argument i at fp[1 + argc - i]
118 // copied to fp[ParsedFunction::kFirstLocalSlotIndex - i]. 120 // copied to fp[ParsedFunction::kFirstLocalSlotIndex - i].
119 const int num_params = num_fixed_params + num_opt_params; 121 const int num_params = num_fixed_params + num_opt_params;
120 122
121 // Total number of args is the first Smi in args descriptor array (EDX). 123 // Total number of args is the first Smi in args descriptor array (EDX).
122 __ movl(EBX, FieldAddress(EDX, Array::data_offset())); 124 __ movl(EBX, FieldAddress(EDX, Array::data_offset()));
123 // Check that num_args <= num_params. 125 // Check that num_args <= num_params.
124 Label wrong_num_arguments; 126 Label wrong_num_arguments;
125 __ cmpl(EBX, Immediate(Smi::RawValue(num_params))); 127 __ cmpl(EBX, Immediate(Smi::RawValue(num_params)));
126 __ j(GREATER, &wrong_num_arguments); 128 __ j(GREATER, &wrong_num_arguments);
127 // Number of positional args is the second Smi in descriptor array (EDX). 129 // Number of positional args is the second Smi in descriptor array (EDX).
128 __ movl(ECX, FieldAddress(EDX, Array::data_offset() + (1 * kWordSize))); 130 __ movl(ECX, FieldAddress(EDX, Array::data_offset() + (1 * kWordSize)));
129 // Check that num_pos_args >= num_fixed_params. 131 // Check that num_pos_args >= num_fixed_params.
130 __ cmpl(ECX, Immediate(Smi::RawValue(num_fixed_params))); 132 __ cmpl(ECX, Immediate(Smi::RawValue(num_fixed_params)));
131 __ j(LESS, &wrong_num_arguments); 133 __ j(LESS, &wrong_num_arguments);
132 // Since EBX and ECX are Smi, use TIMES_2 instead of TIMES_4. 134 // Since EBX and ECX are Smi, use TIMES_2 instead of TIMES_4.
133 // Let EBX point to the last passed positional argument, i.e. to 135 // Let EBX point to the last passed positional argument, i.e. to
134 // fp[1 + num_args - (num_pos_args - 1)]. 136 // fp[1 + num_args - (num_pos_args - 1)].
135 __ subl(EBX, ECX); 137 __ subl(EBX, ECX);
136 __ leal(EBX, Address(EBP, EBX, TIMES_2, 2 * kWordSize)); 138 __ leal(EBX, Address(EBP, EBX, TIMES_2, 2 * kWordSize));
139
137 // Let EDI point to the last copied positional argument, i.e. to 140 // Let EDI point to the last copied positional argument, i.e. to
138 // fp[ParsedFunction::kFirstLocalSlotIndex - (num_pos_args - 1)]. 141 // fp[ParsedFunction::kFirstLocalSlotIndex - (num_pos_args - 1)].
139 const int index = ParsedFunction::kFirstLocalSlotIndex + 1; 142 int implicit_this_param_pos = is_native_instance_closure ? -1 : 0;
143 const int index =
144 ParsedFunction::kFirstLocalSlotIndex + 1 + implicit_this_param_pos;
145 // First copy captured receiver if function is an implicit native closure.
146 if (is_native_instance_closure) {
147 __ movl(EAX, FieldAddress(CTX, Context::variable_offset(0)));
148 __ movl(Address(EBP, (index * kWordSize)), EAX);
149 }
140 __ leal(EDI, Address(EBP, (index * kWordSize))); 150 __ leal(EDI, Address(EBP, (index * kWordSize)));
141 __ subl(EDI, ECX); // ECX is a Smi, subtract twice for TIMES_4 scaling. 151 __ subl(EDI, ECX); // ECX is a Smi, subtract twice for TIMES_4 scaling.
142 __ subl(EDI, ECX); 152 __ subl(EDI, ECX);
143 __ SmiUntag(ECX); 153 __ SmiUntag(ECX);
144 Label loop, loop_condition; 154 Label loop, loop_condition;
145 __ jmp(&loop_condition, Assembler::kNearJump); 155 __ jmp(&loop_condition, Assembler::kNearJump);
146 // We do not use the final allocation index of the variable here, i.e. 156 // We do not use the final allocation index of the variable here, i.e.
147 // scope->VariableAt(i)->index(), because captured variables still need 157 // scope->VariableAt(i)->index(), because captured variables still need
148 // to be copied to the context that is not yet allocated. 158 // to be copied to the context that is not yet allocated.
149 const Address argument_addr(EBX, ECX, TIMES_4, 0); 159 const Address argument_addr(EBX, ECX, TIMES_4, 0);
150 const Address copy_addr(EDI, ECX, TIMES_4, 0); 160 const Address copy_addr(EDI, ECX, TIMES_4, 0);
151 __ Bind(&loop); 161 __ Bind(&loop);
152 __ movl(EAX, argument_addr); 162 __ movl(EAX, argument_addr);
153 __ movl(copy_addr, EAX); 163 __ movl(copy_addr, EAX);
154 __ Bind(&loop_condition); 164 __ Bind(&loop_condition);
155 __ decl(ECX); 165 __ decl(ECX);
156 __ j(POSITIVE, &loop, Assembler::kNearJump); 166 __ j(POSITIVE, &loop, Assembler::kNearJump);
157 167
158 // Copy or initialize optional named arguments. 168 // Copy or initialize optional named arguments.
159 ASSERT(num_opt_params > 0); // Or we would not have to copy arguments. 169 Label all_arguments_processed;
160 // Start by alphabetically sorting the names of the optional parameters.
161 LocalVariable** opt_param = new LocalVariable*[num_opt_params];
162 int* opt_param_position = new int[num_opt_params];
163 for (int pos = num_fixed_params; pos < num_params; pos++) {
164 LocalVariable* parameter = scope->VariableAt(pos);
165 const String& opt_param_name = parameter->name();
166 int i = pos - num_fixed_params;
167 while (--i >= 0) {
168 LocalVariable* param_i = opt_param[i];
169 const intptr_t result = opt_param_name.CompareTo(param_i->name());
170 ASSERT(result != 0);
171 if (result > 0) break;
172 opt_param[i + 1] = opt_param[i];
173 opt_param_position[i + 1] = opt_param_position[i];
174 }
175 opt_param[i + 1] = parameter;
176 opt_param_position[i + 1] = pos;
177 }
178 // Generate code handling each optional parameter in alphabetical order.
179 // Total number of args is the first Smi in args descriptor array (EDX).
180 __ movl(EBX, FieldAddress(EDX, Array::data_offset()));
181 // Number of positional args is the second Smi in descriptor array (EDX).
182 __ movl(ECX, FieldAddress(EDX, Array::data_offset() + (1 * kWordSize)));
183 __ SmiUntag(ECX);
184 // Let EBX point to the first passed argument, i.e. to fp[1 + argc - 0].
185 __ leal(EBX, Address(EBP, EBX, TIMES_2, kWordSize)); // EBX is Smi.
186 // Let EDI point to the name/pos pair of the first named argument.
187 __ leal(EDI, FieldAddress(EDX, Array::data_offset() + (2 * kWordSize)));
188 for (int i = 0; i < num_opt_params; i++) {
189 // Handle this optional parameter only if k or fewer positional arguments
190 // have been passed, where k is the position of this optional parameter in
191 // the formal parameter list.
192 Label load_default_value, assign_optional_parameter, next_parameter;
193 const int param_pos = opt_param_position[i];
194 __ cmpl(ECX, Immediate(param_pos));
195 __ j(GREATER, &next_parameter, Assembler::kNearJump);
196 // Check if this named parameter was passed in.
197 __ movl(EAX, Address(EDI, 0)); // Load EAX with the name of the argument.
198 __ CompareObject(EAX, opt_param[i]->name());
199 __ j(NOT_EQUAL, &load_default_value, Assembler::kNearJump);
200 // Load EAX with passed-in argument at provided arg_pos, i.e. at
201 // fp[1 + argc - arg_pos].
202 __ movl(EAX, Address(EDI, kWordSize)); // EAX is arg_pos as Smi.
203 __ addl(EDI, Immediate(2 * kWordSize)); // Point to next name/pos pair.
204 __ negl(EAX);
205 Address argument_addr(EBX, EAX, TIMES_2, 0); // EAX is a negative Smi.
206 __ movl(EAX, argument_addr);
207 __ jmp(&assign_optional_parameter, Assembler::kNearJump);
208 __ Bind(&load_default_value);
209 // Load EAX with default argument at pos.
210 const Object& value = Object::ZoneHandle(
211 parsed_function().default_parameter_values().At(
212 param_pos - num_fixed_params));
213 __ LoadObject(EAX, value);
214 __ Bind(&assign_optional_parameter);
215 // Assign EAX to fp[ParsedFunction::kFirstLocalSlotIndex - param_pos].
216 // We do not use the final allocation index of the variable here, i.e.
217 // scope->VariableAt(i)->index(), because captured variables still need
218 // to be copied to the context that is not yet allocated.
219 const Address param_addr(
220 EBP, (ParsedFunction::kFirstLocalSlotIndex - param_pos) * kWordSize);
221 __ movl(param_addr, EAX);
222 __ Bind(&next_parameter);
223 }
224 delete[] opt_param;
225 delete[] opt_param_position;
226 // Check that EDI now points to the null terminator in the array descriptor.
227 const Immediate raw_null = 170 const Immediate raw_null =
228 Immediate(reinterpret_cast<intptr_t>(Object::null())); 171 Immediate(reinterpret_cast<intptr_t>(Object::null()));
229 Label all_arguments_processed; 172 if (num_opt_params > 0) {
230 __ cmpl(Address(EDI, 0), raw_null); 173 // Start by alphabetically sorting the names of the optional parameters.
231 __ j(EQUAL, &all_arguments_processed, Assembler::kNearJump); 174 LocalVariable** opt_param = new LocalVariable*[num_opt_params];
175 int* opt_param_position = new int[num_opt_params];
176 for (int pos = num_fixed_params; pos < num_params; pos++) {
177 LocalVariable* parameter = scope->VariableAt(pos);
178 const String& opt_param_name = parameter->name();
179 int i = pos - num_fixed_params;
180 while (--i >= 0) {
181 LocalVariable* param_i = opt_param[i];
182 const intptr_t result = opt_param_name.CompareTo(param_i->name());
183 ASSERT(result != 0);
184 if (result > 0) break;
185 opt_param[i + 1] = opt_param[i];
186 opt_param_position[i + 1] = opt_param_position[i];
187 }
188 opt_param[i + 1] = parameter;
189 opt_param_position[i + 1] = pos;
190 }
191 // Generate code handling each optional parameter in alphabetical order.
192 // Total number of args is the first Smi in args descriptor array (EDX).
193 __ movl(EBX, FieldAddress(EDX, Array::data_offset()));
194 // Number of positional args is the second Smi in descriptor array (EDX).
195 __ movl(ECX, FieldAddress(EDX, Array::data_offset() + (1 * kWordSize)));
196 __ SmiUntag(ECX);
197 // Let EBX point to the first passed argument, i.e. to fp[1 + argc - 0].
198 __ leal(EBX, Address(EBP, EBX, TIMES_2, kWordSize)); // EBX is Smi.
199 // Let EDI point to the name/pos pair of the first named argument.
200 __ leal(EDI, FieldAddress(EDX, Array::data_offset() + (2 * kWordSize)));
201 for (int i = 0; i < num_opt_params; i++) {
202 // Handle this optional parameter only if k or fewer positional arguments
203 // have been passed, where k is the position of this optional parameter in
204 // the formal parameter list.
205 Label load_default_value, assign_optional_parameter, next_parameter;
206 const int param_pos = opt_param_position[i];
207 __ cmpl(ECX, Immediate(param_pos));
208 __ j(GREATER, &next_parameter, Assembler::kNearJump);
209 // Check if this named parameter was passed in.
210 __ movl(EAX, Address(EDI, 0)); // Load EAX with the name of the argument.
211 __ CompareObject(EAX, opt_param[i]->name());
212 __ j(NOT_EQUAL, &load_default_value, Assembler::kNearJump);
213 // Load EAX with passed-in argument at provided arg_pos, i.e. at
214 // fp[1 + argc - arg_pos].
215 __ movl(EAX, Address(EDI, kWordSize)); // EAX is arg_pos as Smi.
216 __ addl(EDI, Immediate(2 * kWordSize)); // Point to next name/pos pair.
217 __ negl(EAX);
218 Address argument_addr(EBX, EAX, TIMES_2, 0); // EAX is a negative Smi.
219 __ movl(EAX, argument_addr);
220 __ jmp(&assign_optional_parameter, Assembler::kNearJump);
221 __ Bind(&load_default_value);
222 // Load EAX with default argument at pos.
223 const Object& value = Object::ZoneHandle(
224 parsed_function().default_parameter_values().At(
225 param_pos - num_fixed_params));
226 __ LoadObject(EAX, value);
227 __ Bind(&assign_optional_parameter);
228 // Assign EAX to fp[ParsedFunction::kFirstLocalSlotIndex - param_pos].
229 // We do not use the final allocation index of the variable here, i.e.
230 // scope->VariableAt(i)->index(), because captured variables still need
231 // to be copied to the context that is not yet allocated.
232 intptr_t computed_param_pos = (ParsedFunction::kFirstLocalSlotIndex -
233 param_pos + implicit_this_param_pos);
234 const Address param_addr(EBP, (computed_param_pos * kWordSize));
235 __ movl(param_addr, EAX);
236 __ Bind(&next_parameter);
237 }
238 delete[] opt_param;
239 delete[] opt_param_position;
240 // Check that EDI now points to the null terminator in the array descriptor.
241 __ cmpl(Address(EDI, 0), raw_null);
242 __ j(EQUAL, &all_arguments_processed, Assembler::kNearJump);
243 } else {
244 ASSERT(is_native_instance_closure);
245 __ jmp(&all_arguments_processed, Assembler::kNearJump);
246 }
232 247
233 __ Bind(&wrong_num_arguments); 248 __ Bind(&wrong_num_arguments);
234 if (StackSize() != 0) { 249 if (StackSize() != 0) {
235 // We need to unwind the space we reserved for locals and copied parameters. 250 // We need to unwind the space we reserved for locals and copied parameters.
236 // The NoSuchMethodFunction stub does not expect to see that area on the 251 // The NoSuchMethodFunction stub does not expect to see that area on the
237 // stack. 252 // stack.
238 __ addl(ESP, Immediate(StackSize() * kWordSize)); 253 __ addl(ESP, Immediate(StackSize() * kWordSize));
239 } 254 }
240 if (function.IsClosureFunction()) { 255 if (function.IsClosureFunction()) {
241 GenerateCallRuntime(AstNode::kNoId, 256 GenerateCallRuntime(AstNode::kNoId,
(...skipping 788 matching lines...) Expand 10 before | Expand all | Expand 10 after
1030 __ cvtsi2sd(result, temp); 1045 __ cvtsi2sd(result, temp);
1031 __ Bind(&done); 1046 __ Bind(&done);
1032 } 1047 }
1033 1048
1034 1049
1035 #undef __ 1050 #undef __
1036 1051
1037 } // namespace dart 1052 } // namespace dart
1038 1053
1039 #endif // defined TARGET_ARCH_IA32 1054 #endif // defined TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « vm/dart_api_impl_test.cc ('k') | vm/flow_graph_compiler_x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698