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

Side by Side Diff: runtime/vm/flow_graph_compiler_arm64.cc

Issue 259903002: Enables all codegen tests for arm64. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 8 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 | « runtime/vm/code_generator_test.cc ('k') | runtime/vm/intermediate_language_arm64.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) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, 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_ARM64. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM64.
6 #if defined(TARGET_ARCH_ARM64) 6 #if defined(TARGET_ARCH_ARM64)
7 7
8 #include "vm/flow_graph_compiler.h" 8 #include "vm/flow_graph_compiler.h"
9 9
10 #include "vm/ast_printer.h" 10 #include "vm/ast_printer.h"
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
167 if (is_optimizing()) { 167 if (is_optimizing()) {
168 return; 168 return;
169 } 169 }
170 Definition* defn = instr->AsDefinition(); 170 Definition* defn = instr->AsDefinition();
171 if ((defn != NULL) && defn->is_used()) { 171 if ((defn != NULL) && defn->is_used()) {
172 __ Push(defn->locs()->out(0).reg()); 172 __ Push(defn->locs()->out(0).reg());
173 } 173 }
174 } 174 }
175 175
176 176
177 // Input parameters:
178 // R4: arguments descriptor array.
177 void FlowGraphCompiler::CopyParameters() { 179 void FlowGraphCompiler::CopyParameters() {
178 UNIMPLEMENTED(); 180 __ Comment("Copy parameters");
181 const Function& function = parsed_function().function();
182 LocalScope* scope = parsed_function().node_sequence()->scope();
183 const int num_fixed_params = function.num_fixed_parameters();
184 const int num_opt_pos_params = function.NumOptionalPositionalParameters();
185 const int num_opt_named_params = function.NumOptionalNamedParameters();
186 const int num_params =
187 num_fixed_params + num_opt_pos_params + num_opt_named_params;
188 ASSERT(function.NumParameters() == num_params);
189 ASSERT(parsed_function().first_parameter_index() == kFirstLocalSlotFromFp);
190
191 // Check that min_num_pos_args <= num_pos_args <= max_num_pos_args,
192 // where num_pos_args is the number of positional arguments passed in.
193 const int min_num_pos_args = num_fixed_params;
194 const int max_num_pos_args = num_fixed_params + num_opt_pos_params;
195
196 __ LoadFieldFromOffset(
197 R8, R4, ArgumentsDescriptor::positional_count_offset());
198 // Check that min_num_pos_args <= num_pos_args.
199 Label wrong_num_arguments;
200 __ CompareImmediate(R8, Smi::RawValue(min_num_pos_args), PP);
201 __ b(&wrong_num_arguments, LT);
202 // Check that num_pos_args <= max_num_pos_args.
203 __ CompareImmediate(R8, Smi::RawValue(max_num_pos_args), PP);
204 __ b(&wrong_num_arguments, GT);
205
206 // Copy positional arguments.
207 // Argument i passed at fp[kParamEndSlotFromFp + num_args - i] is copied
208 // to fp[kFirstLocalSlotFromFp - i].
209
210 __ LoadFieldFromOffset(R7, R4, ArgumentsDescriptor::count_offset());
211 // Since R7 and R8 are Smi, use LSL 2 instead of LSL 3.
212 // Let R7 point to the last passed positional argument, i.e. to
213 // fp[kParamEndSlotFromFp + num_args - (num_pos_args - 1)].
214 __ sub(R7, R7, Operand(R8));
215 __ add(R7, FP, Operand(R7, LSL, 2));
216 __ add(R7, R7, Operand((kParamEndSlotFromFp + 1) * kWordSize));
217
218 // Let R6 point to the last copied positional argument, i.e. to
219 // fp[kFirstLocalSlotFromFp - (num_pos_args - 1)].
220 __ AddImmediate(R6, FP, (kFirstLocalSlotFromFp + 1) * kWordSize, PP);
221 __ sub(R6, R6, Operand(R8, LSL, 2)); // R8 is a Smi.
222 __ SmiUntag(R8);
223 Label loop, loop_condition;
224 __ b(&loop_condition);
225 // We do not use the final allocation index of the variable here, i.e.
226 // scope->VariableAt(i)->index(), because captured variables still need
227 // to be copied to the context that is not yet allocated.
228 const Address argument_addr(R7, R8, UXTX, Address::Scaled);
229 const Address copy_addr(R6, R8, UXTX, Address::Scaled);
230 __ Bind(&loop);
231 __ ldr(TMP, argument_addr);
232 __ str(TMP, copy_addr);
233 __ Bind(&loop_condition);
234 __ subs(R8, R8, Operand(1));
235 __ b(&loop, PL);
236
237 // Copy or initialize optional named arguments.
238 Label all_arguments_processed;
239 #ifdef DEBUG
240 const bool check_correct_named_args = true;
241 #else
242 const bool check_correct_named_args = function.IsClosureFunction();
243 #endif
244 if (num_opt_named_params > 0) {
245 // Start by alphabetically sorting the names of the optional parameters.
246 LocalVariable** opt_param = new LocalVariable*[num_opt_named_params];
247 int* opt_param_position = new int[num_opt_named_params];
248 for (int pos = num_fixed_params; pos < num_params; pos++) {
249 LocalVariable* parameter = scope->VariableAt(pos);
250 const String& opt_param_name = parameter->name();
251 int i = pos - num_fixed_params;
252 while (--i >= 0) {
253 LocalVariable* param_i = opt_param[i];
254 const intptr_t result = opt_param_name.CompareTo(param_i->name());
255 ASSERT(result != 0);
256 if (result > 0) break;
257 opt_param[i + 1] = opt_param[i];
258 opt_param_position[i + 1] = opt_param_position[i];
259 }
260 opt_param[i + 1] = parameter;
261 opt_param_position[i + 1] = pos;
262 }
263 // Generate code handling each optional parameter in alphabetical order.
264 __ LoadFieldFromOffset(R7, R4, ArgumentsDescriptor::count_offset());
265 __ LoadFieldFromOffset(
266 R8, R4, ArgumentsDescriptor::positional_count_offset());
267 __ SmiUntag(R8);
268 // Let R7 point to the first passed argument, i.e. to
269 // fp[kParamEndSlotFromFp + num_args - 0]; num_args (R7) is Smi.
270 __ add(R7, FP, Operand(R7, LSL, 2));
271 __ AddImmediate(R7, R7, kParamEndSlotFromFp * kWordSize, PP);
272 // Let R6 point to the entry of the first named argument.
273 __ add(R6, R4, Operand(
274 ArgumentsDescriptor::first_named_entry_offset() - kHeapObjectTag));
275 for (int i = 0; i < num_opt_named_params; i++) {
276 Label load_default_value, assign_optional_parameter;
277 const int param_pos = opt_param_position[i];
278 // Check if this named parameter was passed in.
279 // Load R5 with the name of the argument.
280 __ LoadFromOffset(R5, R6, ArgumentsDescriptor::name_offset());
281 ASSERT(opt_param[i]->name().IsSymbol());
282 __ CompareObject(R5, opt_param[i]->name(), PP);
283 __ b(&load_default_value, NE);
284 // Load R5 with passed-in argument at provided arg_pos, i.e. at
285 // fp[kParamEndSlotFromFp + num_args - arg_pos].
286 __ LoadFromOffset(R5, R6, ArgumentsDescriptor::position_offset());
287 // R5 is arg_pos as Smi.
288 // Point to next named entry.
289 __ add(R6, R6, Operand(ArgumentsDescriptor::named_entry_size()));
290 // Negate and untag R5 so we can use in scaled address mode.
291 __ subs(R5, ZR, Operand(R5, ASR, 1));
292 Address argument_addr(R7, R5, UXTX, Address::Scaled); // R5 is untagged.
293 __ ldr(R5, argument_addr);
294 __ b(&assign_optional_parameter);
295 __ Bind(&load_default_value);
296 // Load R5 with default argument.
297 const Object& value = Object::ZoneHandle(
298 parsed_function().default_parameter_values().At(
299 param_pos - num_fixed_params));
300 __ LoadObject(R5, value, PP);
301 __ Bind(&assign_optional_parameter);
302 // Assign R5 to fp[kFirstLocalSlotFromFp - param_pos].
303 // We do not use the final allocation index of the variable here, i.e.
304 // scope->VariableAt(i)->index(), because captured variables still need
305 // to be copied to the context that is not yet allocated.
306 const intptr_t computed_param_pos = kFirstLocalSlotFromFp - param_pos;
307 __ StoreToOffset(R5, FP, computed_param_pos * kWordSize);
308 }
309 delete[] opt_param;
310 delete[] opt_param_position;
311 if (check_correct_named_args) {
312 // Check that R6 now points to the null terminator in the arguments
313 // descriptor.
314 __ ldr(R5, Address(R6));
315 __ LoadObject(TMP, Object::null_object(), PP);
316 __ CompareRegisters(R5, TMP);
317 __ b(&all_arguments_processed, EQ);
318 }
319 } else {
320 ASSERT(num_opt_pos_params > 0);
321 __ LoadFieldFromOffset(
322 R8, R4, ArgumentsDescriptor::positional_count_offset());
323 __ SmiUntag(R8);
324 for (int i = 0; i < num_opt_pos_params; i++) {
325 Label next_parameter;
326 // Handle this optional positional parameter only if k or fewer positional
327 // arguments have been passed, where k is param_pos, the position of this
328 // optional parameter in the formal parameter list.
329 const int param_pos = num_fixed_params + i;
330 __ CompareImmediate(R8, param_pos, PP);
331 __ b(&next_parameter, GT);
332 // Load R5 with default argument.
333 const Object& value = Object::ZoneHandle(
334 parsed_function().default_parameter_values().At(i));
335 __ LoadObject(R5, value, PP);
336 // Assign R5 to fp[kFirstLocalSlotFromFp - param_pos].
337 // We do not use the final allocation index of the variable here, i.e.
338 // scope->VariableAt(i)->index(), because captured variables still need
339 // to be copied to the context that is not yet allocated.
340 const intptr_t computed_param_pos = kFirstLocalSlotFromFp - param_pos;
341 __ StoreToOffset(R5, FP, computed_param_pos * kWordSize);
342 __ Bind(&next_parameter);
343 }
344 if (check_correct_named_args) {
345 __ LoadFieldFromOffset(R7, R4, ArgumentsDescriptor::count_offset());
346 __ SmiUntag(R7);
347 // Check that R8 equals R7, i.e. no named arguments passed.
348 __ CompareRegisters(R8, R7);
349 __ b(&all_arguments_processed, EQ);
350 }
351 }
352
353 __ Bind(&wrong_num_arguments);
354 if (function.IsClosureFunction()) {
355 // Invoke noSuchMethod function passing "call" as the original name.
356 const int kNumArgsChecked = 1;
357 const ICData& ic_data = ICData::ZoneHandle(
358 ICData::New(function, Symbols::Call(), Object::empty_array(),
359 Isolate::kNoDeoptId, kNumArgsChecked));
360 __ LoadObject(R5, ic_data, PP);
361 __ LeaveDartFrame(); // The arguments are still on the stack.
362 __ Branch(&StubCode::CallNoSuchMethodFunctionLabel(), PP);
363 // The noSuchMethod call may return to the caller, but not here.
364 __ hlt(0);
365 } else if (check_correct_named_args) {
366 __ Stop("Wrong arguments");
367 }
368
369 __ Bind(&all_arguments_processed);
370 // Nullify originally passed arguments only after they have been copied and
371 // checked, otherwise noSuchMethod would not see their original values.
372 // This step can be skipped in case we decide that formal parameters are
373 // implicitly final, since garbage collecting the unmodified value is not
374 // an issue anymore.
375
376 // R4 : arguments descriptor array.
377 __ LoadFieldFromOffset(R8, R4, ArgumentsDescriptor::count_offset());
378 __ SmiUntag(R8);
379 __ add(R7, FP, Operand((kParamEndSlotFromFp + 1) * kWordSize));
380 const Address original_argument_addr(R7, R8, UXTX, Address::Scaled);
381 __ LoadObject(TMP, Object::null_object(), PP);
382 Label null_args_loop, null_args_loop_condition;
383 __ b(&null_args_loop_condition);
384 __ Bind(&null_args_loop);
385 __ str(TMP, original_argument_addr);
386 __ Bind(&null_args_loop_condition);
387 __ subs(R8, R8, Operand(1));
388 __ b(&null_args_loop, PL);
179 } 389 }
180 390
181 391
182 void FlowGraphCompiler::GenerateInlinedGetter(intptr_t offset) { 392 void FlowGraphCompiler::GenerateInlinedGetter(intptr_t offset) {
183 UNIMPLEMENTED(); 393 UNIMPLEMENTED();
184 } 394 }
185 395
186 396
187 void FlowGraphCompiler::GenerateInlinedSetter(intptr_t offset) { 397 void FlowGraphCompiler::GenerateInlinedSetter(intptr_t offset) {
188 UNIMPLEMENTED(); 398 UNIMPLEMENTED();
(...skipping 506 matching lines...) Expand 10 before | Expand all | Expand 10 after
695 void ParallelMoveResolver::RestoreFpuScratch(FpuRegister reg) { 905 void ParallelMoveResolver::RestoreFpuScratch(FpuRegister reg) {
696 UNIMPLEMENTED(); 906 UNIMPLEMENTED();
697 } 907 }
698 908
699 909
700 #undef __ 910 #undef __
701 911
702 } // namespace dart 912 } // namespace dart
703 913
704 #endif // defined TARGET_ARCH_ARM64 914 #endif // defined TARGET_ARCH_ARM64
OLDNEW
« no previous file with comments | « runtime/vm/code_generator_test.cc ('k') | runtime/vm/intermediate_language_arm64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698