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

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

Issue 269343010: Adds single-precision and SIMD load/store to arm64. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 7 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/disassembler_arm64.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 237 matching lines...) Expand 10 before | Expand all | Expand 10 after
248 const intptr_t from_index = num_type_args - num_type_params; 248 const intptr_t from_index = num_type_args - num_type_params;
249 const TypeArguments& type_arguments = 249 const TypeArguments& type_arguments =
250 TypeArguments::ZoneHandle(type.arguments()); 250 TypeArguments::ZoneHandle(type.arguments());
251 const bool is_raw_type = type_arguments.IsNull() || 251 const bool is_raw_type = type_arguments.IsNull() ||
252 type_arguments.IsRaw(from_index, num_type_params); 252 type_arguments.IsRaw(from_index, num_type_params);
253 // Signature class is an instantiated parameterized type. 253 // Signature class is an instantiated parameterized type.
254 if (!type_class.IsSignatureClass()) { 254 if (!type_class.IsSignatureClass()) {
255 if (is_raw_type) { 255 if (is_raw_type) {
256 const Register kClassIdReg = R2; 256 const Register kClassIdReg = R2;
257 // dynamic type argument, check only classes. 257 // dynamic type argument, check only classes.
258 __ LoadClassId(kClassIdReg, kInstanceReg); 258 __ LoadClassId(kClassIdReg, kInstanceReg, PP);
259 __ CompareImmediate(kClassIdReg, type_class.id(), PP); 259 __ CompareImmediate(kClassIdReg, type_class.id(), PP);
260 __ b(is_instance_lbl, EQ); 260 __ b(is_instance_lbl, EQ);
261 // List is a very common case. 261 // List is a very common case.
262 if (IsListClass(type_class)) { 262 if (IsListClass(type_class)) {
263 GenerateListTypeCheck(kClassIdReg, is_instance_lbl); 263 GenerateListTypeCheck(kClassIdReg, is_instance_lbl);
264 } 264 }
265 return GenerateSubtype1TestCacheLookup( 265 return GenerateSubtype1TestCacheLookup(
266 token_pos, type_class, is_instance_lbl, is_not_instance_lbl); 266 token_pos, type_class, is_instance_lbl, is_not_instance_lbl);
267 } 267 }
268 // If one type argument only, check if type argument is Object or dynamic. 268 // If one type argument only, check if type argument is Object or dynamic.
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
329 if (smi_class.IsSubtypeOf(TypeArguments::Handle(), 329 if (smi_class.IsSubtypeOf(TypeArguments::Handle(),
330 type_class, 330 type_class,
331 TypeArguments::Handle(), 331 TypeArguments::Handle(),
332 NULL)) { 332 NULL)) {
333 __ b(is_instance_lbl, EQ); 333 __ b(is_instance_lbl, EQ);
334 } else { 334 } else {
335 __ b(is_not_instance_lbl, EQ); 335 __ b(is_not_instance_lbl, EQ);
336 } 336 }
337 // Compare if the classes are equal. 337 // Compare if the classes are equal.
338 const Register kClassIdReg = R2; 338 const Register kClassIdReg = R2;
339 __ LoadClassId(kClassIdReg, kInstanceReg); 339 __ LoadClassId(kClassIdReg, kInstanceReg, PP);
340 __ CompareImmediate(kClassIdReg, type_class.id(), PP); 340 __ CompareImmediate(kClassIdReg, type_class.id(), PP);
341 __ b(is_instance_lbl, EQ); 341 __ b(is_instance_lbl, EQ);
342 // See ClassFinalizer::ResolveSuperTypeAndInterfaces for list of restricted 342 // See ClassFinalizer::ResolveSuperTypeAndInterfaces for list of restricted
343 // interfaces. 343 // interfaces.
344 // Bool interface can be implemented only by core class Bool. 344 // Bool interface can be implemented only by core class Bool.
345 if (type.IsBoolType()) { 345 if (type.IsBoolType()) {
346 __ CompareImmediate(kClassIdReg, kBoolCid, PP); 346 __ CompareImmediate(kClassIdReg, kBoolCid, PP);
347 __ b(is_instance_lbl, EQ); 347 __ b(is_instance_lbl, EQ);
348 __ b(is_not_instance_lbl); 348 __ b(is_not_instance_lbl);
349 return false; 349 return false;
350 } 350 }
351 if (type.IsFunctionType()) { 351 if (type.IsFunctionType()) {
352 // Check if instance is a closure. 352 // Check if instance is a closure.
353 __ LoadClassById(R3, kClassIdReg); 353 __ LoadClassById(R3, kClassIdReg, PP);
354 __ LoadFieldFromOffset(R3, R3, Class::signature_function_offset()); 354 __ LoadFieldFromOffset(R3, R3, Class::signature_function_offset(), PP);
355 __ CompareObject(R3, Object::null_object(), PP); 355 __ CompareObject(R3, Object::null_object(), PP);
356 __ b(is_instance_lbl, NE); 356 __ b(is_instance_lbl, NE);
357 } 357 }
358 // Custom checking for numbers (Smi, Mint, Bigint and Double). 358 // Custom checking for numbers (Smi, Mint, Bigint and Double).
359 // Note that instance is not Smi (checked above). 359 // Note that instance is not Smi (checked above).
360 if (type.IsSubtypeOf(Type::Handle(Type::Number()), NULL)) { 360 if (type.IsSubtypeOf(Type::Handle(Type::Number()), NULL)) {
361 GenerateNumberTypeCheck( 361 GenerateNumberTypeCheck(
362 kClassIdReg, type, is_instance_lbl, is_not_instance_lbl); 362 kClassIdReg, type, is_instance_lbl, is_not_instance_lbl);
363 return false; 363 return false;
364 } 364 }
(...skipping 13 matching lines...) Expand all
378 // TODO(srdjan): Implement a quicker subtype check, as type test 378 // TODO(srdjan): Implement a quicker subtype check, as type test
379 // arrays can grow too high, but they may be useful when optimizing 379 // arrays can grow too high, but they may be useful when optimizing
380 // code (type-feedback). 380 // code (type-feedback).
381 RawSubtypeTestCache* FlowGraphCompiler::GenerateSubtype1TestCacheLookup( 381 RawSubtypeTestCache* FlowGraphCompiler::GenerateSubtype1TestCacheLookup(
382 intptr_t token_pos, 382 intptr_t token_pos,
383 const Class& type_class, 383 const Class& type_class,
384 Label* is_instance_lbl, 384 Label* is_instance_lbl,
385 Label* is_not_instance_lbl) { 385 Label* is_not_instance_lbl) {
386 __ Comment("Subtype1TestCacheLookup"); 386 __ Comment("Subtype1TestCacheLookup");
387 const Register kInstanceReg = R0; 387 const Register kInstanceReg = R0;
388 __ LoadClass(R1, kInstanceReg); 388 __ LoadClass(R1, kInstanceReg, PP);
389 // R1: instance class. 389 // R1: instance class.
390 // Check immediate superclass equality. 390 // Check immediate superclass equality.
391 __ LoadFieldFromOffset(R2, R1, Class::super_type_offset()); 391 __ LoadFieldFromOffset(R2, R1, Class::super_type_offset(), PP);
392 __ LoadFieldFromOffset(R2, R2, Type::type_class_offset()); 392 __ LoadFieldFromOffset(R2, R2, Type::type_class_offset(), PP);
393 __ CompareObject(R2, type_class, PP); 393 __ CompareObject(R2, type_class, PP);
394 __ b(is_instance_lbl, EQ); 394 __ b(is_instance_lbl, EQ);
395 395
396 const Register kTypeArgumentsReg = kNoRegister; 396 const Register kTypeArgumentsReg = kNoRegister;
397 const Register kTempReg = kNoRegister; 397 const Register kTempReg = kNoRegister;
398 return GenerateCallSubtypeTestStub(kTestTypeOneArg, 398 return GenerateCallSubtypeTestStub(kTestTypeOneArg,
399 kInstanceReg, 399 kInstanceReg,
400 kTypeArgumentsReg, 400 kTypeArgumentsReg,
401 kTempReg, 401 kTempReg,
402 is_instance_lbl, 402 is_instance_lbl,
(...skipping 13 matching lines...) Expand all
416 // Skip check if destination is a dynamic type. 416 // Skip check if destination is a dynamic type.
417 if (type.IsTypeParameter()) { 417 if (type.IsTypeParameter()) {
418 const TypeParameter& type_param = TypeParameter::Cast(type); 418 const TypeParameter& type_param = TypeParameter::Cast(type);
419 // Load instantiator (or null) and instantiator type arguments on stack. 419 // Load instantiator (or null) and instantiator type arguments on stack.
420 __ ldr(R1, Address(SP)); // Get instantiator type arguments. 420 __ ldr(R1, Address(SP)); // Get instantiator type arguments.
421 // R1: instantiator type arguments. 421 // R1: instantiator type arguments.
422 // Check if type arguments are null, i.e. equivalent to vector of dynamic. 422 // Check if type arguments are null, i.e. equivalent to vector of dynamic.
423 __ CompareObject(R1, Object::null_object(), PP); 423 __ CompareObject(R1, Object::null_object(), PP);
424 __ b(is_instance_lbl, EQ); 424 __ b(is_instance_lbl, EQ);
425 __ LoadFieldFromOffset( 425 __ LoadFieldFromOffset(
426 R2, R1, TypeArguments::type_at_offset(type_param.index())); 426 R2, R1, TypeArguments::type_at_offset(type_param.index()), PP);
427 // R2: concrete type of type. 427 // R2: concrete type of type.
428 // Check if type argument is dynamic. 428 // Check if type argument is dynamic.
429 __ CompareObject(R2, Type::ZoneHandle(Type::DynamicType()), PP); 429 __ CompareObject(R2, Type::ZoneHandle(Type::DynamicType()), PP);
430 __ b(is_instance_lbl, EQ); 430 __ b(is_instance_lbl, EQ);
431 __ CompareObject(R2, Type::ZoneHandle(Type::ObjectType()), PP); 431 __ CompareObject(R2, Type::ZoneHandle(Type::ObjectType()), PP);
432 __ b(is_instance_lbl, EQ); 432 __ b(is_instance_lbl, EQ);
433 433
434 // For Smi check quickly against int and num interfaces. 434 // For Smi check quickly against int and num interfaces.
435 Label not_smi; 435 Label not_smi;
436 __ tsti(R0, kSmiTagMask); // Value is Smi? 436 __ tsti(R0, kSmiTagMask); // Value is Smi?
(...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after
731 num_fixed_params + num_opt_pos_params + num_opt_named_params; 731 num_fixed_params + num_opt_pos_params + num_opt_named_params;
732 ASSERT(function.NumParameters() == num_params); 732 ASSERT(function.NumParameters() == num_params);
733 ASSERT(parsed_function().first_parameter_index() == kFirstLocalSlotFromFp); 733 ASSERT(parsed_function().first_parameter_index() == kFirstLocalSlotFromFp);
734 734
735 // Check that min_num_pos_args <= num_pos_args <= max_num_pos_args, 735 // Check that min_num_pos_args <= num_pos_args <= max_num_pos_args,
736 // where num_pos_args is the number of positional arguments passed in. 736 // where num_pos_args is the number of positional arguments passed in.
737 const int min_num_pos_args = num_fixed_params; 737 const int min_num_pos_args = num_fixed_params;
738 const int max_num_pos_args = num_fixed_params + num_opt_pos_params; 738 const int max_num_pos_args = num_fixed_params + num_opt_pos_params;
739 739
740 __ LoadFieldFromOffset( 740 __ LoadFieldFromOffset(
741 R8, R4, ArgumentsDescriptor::positional_count_offset()); 741 R8, R4, ArgumentsDescriptor::positional_count_offset(), PP);
742 // Check that min_num_pos_args <= num_pos_args. 742 // Check that min_num_pos_args <= num_pos_args.
743 Label wrong_num_arguments; 743 Label wrong_num_arguments;
744 __ CompareImmediate(R8, Smi::RawValue(min_num_pos_args), PP); 744 __ CompareImmediate(R8, Smi::RawValue(min_num_pos_args), PP);
745 __ b(&wrong_num_arguments, LT); 745 __ b(&wrong_num_arguments, LT);
746 // Check that num_pos_args <= max_num_pos_args. 746 // Check that num_pos_args <= max_num_pos_args.
747 __ CompareImmediate(R8, Smi::RawValue(max_num_pos_args), PP); 747 __ CompareImmediate(R8, Smi::RawValue(max_num_pos_args), PP);
748 __ b(&wrong_num_arguments, GT); 748 __ b(&wrong_num_arguments, GT);
749 749
750 // Copy positional arguments. 750 // Copy positional arguments.
751 // Argument i passed at fp[kParamEndSlotFromFp + num_args - i] is copied 751 // Argument i passed at fp[kParamEndSlotFromFp + num_args - i] is copied
752 // to fp[kFirstLocalSlotFromFp - i]. 752 // to fp[kFirstLocalSlotFromFp - i].
753 753
754 __ LoadFieldFromOffset(R7, R4, ArgumentsDescriptor::count_offset()); 754 __ LoadFieldFromOffset(R7, R4, ArgumentsDescriptor::count_offset(), PP);
755 // Since R7 and R8 are Smi, use LSL 2 instead of LSL 3. 755 // Since R7 and R8 are Smi, use LSL 2 instead of LSL 3.
756 // Let R7 point to the last passed positional argument, i.e. to 756 // Let R7 point to the last passed positional argument, i.e. to
757 // fp[kParamEndSlotFromFp + num_args - (num_pos_args - 1)]. 757 // fp[kParamEndSlotFromFp + num_args - (num_pos_args - 1)].
758 __ sub(R7, R7, Operand(R8)); 758 __ sub(R7, R7, Operand(R8));
759 __ add(R7, FP, Operand(R7, LSL, 2)); 759 __ add(R7, FP, Operand(R7, LSL, 2));
760 __ add(R7, R7, Operand((kParamEndSlotFromFp + 1) * kWordSize)); 760 __ add(R7, R7, Operand((kParamEndSlotFromFp + 1) * kWordSize));
761 761
762 // Let R6 point to the last copied positional argument, i.e. to 762 // Let R6 point to the last copied positional argument, i.e. to
763 // fp[kFirstLocalSlotFromFp - (num_pos_args - 1)]. 763 // fp[kFirstLocalSlotFromFp - (num_pos_args - 1)].
764 __ AddImmediate(R6, FP, (kFirstLocalSlotFromFp + 1) * kWordSize, PP); 764 __ AddImmediate(R6, FP, (kFirstLocalSlotFromFp + 1) * kWordSize, PP);
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
798 const intptr_t result = opt_param_name.CompareTo(param_i->name()); 798 const intptr_t result = opt_param_name.CompareTo(param_i->name());
799 ASSERT(result != 0); 799 ASSERT(result != 0);
800 if (result > 0) break; 800 if (result > 0) break;
801 opt_param[i + 1] = opt_param[i]; 801 opt_param[i + 1] = opt_param[i];
802 opt_param_position[i + 1] = opt_param_position[i]; 802 opt_param_position[i + 1] = opt_param_position[i];
803 } 803 }
804 opt_param[i + 1] = parameter; 804 opt_param[i + 1] = parameter;
805 opt_param_position[i + 1] = pos; 805 opt_param_position[i + 1] = pos;
806 } 806 }
807 // Generate code handling each optional parameter in alphabetical order. 807 // Generate code handling each optional parameter in alphabetical order.
808 __ LoadFieldFromOffset(R7, R4, ArgumentsDescriptor::count_offset()); 808 __ LoadFieldFromOffset(R7, R4, ArgumentsDescriptor::count_offset(), PP);
809 __ LoadFieldFromOffset( 809 __ LoadFieldFromOffset(
810 R8, R4, ArgumentsDescriptor::positional_count_offset()); 810 R8, R4, ArgumentsDescriptor::positional_count_offset(), PP);
811 __ SmiUntag(R8); 811 __ SmiUntag(R8);
812 // Let R7 point to the first passed argument, i.e. to 812 // Let R7 point to the first passed argument, i.e. to
813 // fp[kParamEndSlotFromFp + num_args - 0]; num_args (R7) is Smi. 813 // fp[kParamEndSlotFromFp + num_args - 0]; num_args (R7) is Smi.
814 __ add(R7, FP, Operand(R7, LSL, 2)); 814 __ add(R7, FP, Operand(R7, LSL, 2));
815 __ AddImmediate(R7, R7, kParamEndSlotFromFp * kWordSize, PP); 815 __ AddImmediate(R7, R7, kParamEndSlotFromFp * kWordSize, PP);
816 // Let R6 point to the entry of the first named argument. 816 // Let R6 point to the entry of the first named argument.
817 __ add(R6, R4, Operand( 817 __ add(R6, R4, Operand(
818 ArgumentsDescriptor::first_named_entry_offset() - kHeapObjectTag)); 818 ArgumentsDescriptor::first_named_entry_offset() - kHeapObjectTag));
819 for (int i = 0; i < num_opt_named_params; i++) { 819 for (int i = 0; i < num_opt_named_params; i++) {
820 Label load_default_value, assign_optional_parameter; 820 Label load_default_value, assign_optional_parameter;
821 const int param_pos = opt_param_position[i]; 821 const int param_pos = opt_param_position[i];
822 // Check if this named parameter was passed in. 822 // Check if this named parameter was passed in.
823 // Load R5 with the name of the argument. 823 // Load R5 with the name of the argument.
824 __ LoadFromOffset(R5, R6, ArgumentsDescriptor::name_offset()); 824 __ LoadFromOffset(R5, R6, ArgumentsDescriptor::name_offset(), PP);
825 ASSERT(opt_param[i]->name().IsSymbol()); 825 ASSERT(opt_param[i]->name().IsSymbol());
826 __ CompareObject(R5, opt_param[i]->name(), PP); 826 __ CompareObject(R5, opt_param[i]->name(), PP);
827 __ b(&load_default_value, NE); 827 __ b(&load_default_value, NE);
828 // Load R5 with passed-in argument at provided arg_pos, i.e. at 828 // Load R5 with passed-in argument at provided arg_pos, i.e. at
829 // fp[kParamEndSlotFromFp + num_args - arg_pos]. 829 // fp[kParamEndSlotFromFp + num_args - arg_pos].
830 __ LoadFromOffset(R5, R6, ArgumentsDescriptor::position_offset()); 830 __ LoadFromOffset(R5, R6, ArgumentsDescriptor::position_offset(), PP);
831 // R5 is arg_pos as Smi. 831 // R5 is arg_pos as Smi.
832 // Point to next named entry. 832 // Point to next named entry.
833 __ add(R6, R6, Operand(ArgumentsDescriptor::named_entry_size())); 833 __ add(R6, R6, Operand(ArgumentsDescriptor::named_entry_size()));
834 // Negate and untag R5 so we can use in scaled address mode. 834 // Negate and untag R5 so we can use in scaled address mode.
835 __ subs(R5, ZR, Operand(R5, ASR, 1)); 835 __ subs(R5, ZR, Operand(R5, ASR, 1));
836 Address argument_addr(R7, R5, UXTX, Address::Scaled); // R5 is untagged. 836 Address argument_addr(R7, R5, UXTX, Address::Scaled); // R5 is untagged.
837 __ ldr(R5, argument_addr); 837 __ ldr(R5, argument_addr);
838 __ b(&assign_optional_parameter); 838 __ b(&assign_optional_parameter);
839 __ Bind(&load_default_value); 839 __ Bind(&load_default_value);
840 // Load R5 with default argument. 840 // Load R5 with default argument.
841 const Object& value = Object::ZoneHandle( 841 const Object& value = Object::ZoneHandle(
842 parsed_function().default_parameter_values().At( 842 parsed_function().default_parameter_values().At(
843 param_pos - num_fixed_params)); 843 param_pos - num_fixed_params));
844 __ LoadObject(R5, value, PP); 844 __ LoadObject(R5, value, PP);
845 __ Bind(&assign_optional_parameter); 845 __ Bind(&assign_optional_parameter);
846 // Assign R5 to fp[kFirstLocalSlotFromFp - param_pos]. 846 // Assign R5 to fp[kFirstLocalSlotFromFp - param_pos].
847 // We do not use the final allocation index of the variable here, i.e. 847 // We do not use the final allocation index of the variable here, i.e.
848 // scope->VariableAt(i)->index(), because captured variables still need 848 // scope->VariableAt(i)->index(), because captured variables still need
849 // to be copied to the context that is not yet allocated. 849 // to be copied to the context that is not yet allocated.
850 const intptr_t computed_param_pos = kFirstLocalSlotFromFp - param_pos; 850 const intptr_t computed_param_pos = kFirstLocalSlotFromFp - param_pos;
851 __ StoreToOffset(R5, FP, computed_param_pos * kWordSize); 851 __ StoreToOffset(R5, FP, computed_param_pos * kWordSize, PP);
852 } 852 }
853 delete[] opt_param; 853 delete[] opt_param;
854 delete[] opt_param_position; 854 delete[] opt_param_position;
855 if (check_correct_named_args) { 855 if (check_correct_named_args) {
856 // Check that R6 now points to the null terminator in the arguments 856 // Check that R6 now points to the null terminator in the arguments
857 // descriptor. 857 // descriptor.
858 __ ldr(R5, Address(R6)); 858 __ ldr(R5, Address(R6));
859 __ CompareObject(R5, Object::null_object(), PP); 859 __ CompareObject(R5, Object::null_object(), PP);
860 __ b(&all_arguments_processed, EQ); 860 __ b(&all_arguments_processed, EQ);
861 } 861 }
862 } else { 862 } else {
863 ASSERT(num_opt_pos_params > 0); 863 ASSERT(num_opt_pos_params > 0);
864 __ LoadFieldFromOffset( 864 __ LoadFieldFromOffset(
865 R8, R4, ArgumentsDescriptor::positional_count_offset()); 865 R8, R4, ArgumentsDescriptor::positional_count_offset(), PP);
866 __ SmiUntag(R8); 866 __ SmiUntag(R8);
867 for (int i = 0; i < num_opt_pos_params; i++) { 867 for (int i = 0; i < num_opt_pos_params; i++) {
868 Label next_parameter; 868 Label next_parameter;
869 // Handle this optional positional parameter only if k or fewer positional 869 // Handle this optional positional parameter only if k or fewer positional
870 // arguments have been passed, where k is param_pos, the position of this 870 // arguments have been passed, where k is param_pos, the position of this
871 // optional parameter in the formal parameter list. 871 // optional parameter in the formal parameter list.
872 const int param_pos = num_fixed_params + i; 872 const int param_pos = num_fixed_params + i;
873 __ CompareImmediate(R8, param_pos, PP); 873 __ CompareImmediate(R8, param_pos, PP);
874 __ b(&next_parameter, GT); 874 __ b(&next_parameter, GT);
875 // Load R5 with default argument. 875 // Load R5 with default argument.
876 const Object& value = Object::ZoneHandle( 876 const Object& value = Object::ZoneHandle(
877 parsed_function().default_parameter_values().At(i)); 877 parsed_function().default_parameter_values().At(i));
878 __ LoadObject(R5, value, PP); 878 __ LoadObject(R5, value, PP);
879 // Assign R5 to fp[kFirstLocalSlotFromFp - param_pos]. 879 // Assign R5 to fp[kFirstLocalSlotFromFp - param_pos].
880 // We do not use the final allocation index of the variable here, i.e. 880 // We do not use the final allocation index of the variable here, i.e.
881 // scope->VariableAt(i)->index(), because captured variables still need 881 // scope->VariableAt(i)->index(), because captured variables still need
882 // to be copied to the context that is not yet allocated. 882 // to be copied to the context that is not yet allocated.
883 const intptr_t computed_param_pos = kFirstLocalSlotFromFp - param_pos; 883 const intptr_t computed_param_pos = kFirstLocalSlotFromFp - param_pos;
884 __ StoreToOffset(R5, FP, computed_param_pos * kWordSize); 884 __ StoreToOffset(R5, FP, computed_param_pos * kWordSize, PP);
885 __ Bind(&next_parameter); 885 __ Bind(&next_parameter);
886 } 886 }
887 if (check_correct_named_args) { 887 if (check_correct_named_args) {
888 __ LoadFieldFromOffset(R7, R4, ArgumentsDescriptor::count_offset()); 888 __ LoadFieldFromOffset(R7, R4, ArgumentsDescriptor::count_offset(), PP);
889 __ SmiUntag(R7); 889 __ SmiUntag(R7);
890 // Check that R8 equals R7, i.e. no named arguments passed. 890 // Check that R8 equals R7, i.e. no named arguments passed.
891 __ CompareRegisters(R8, R7); 891 __ CompareRegisters(R8, R7);
892 __ b(&all_arguments_processed, EQ); 892 __ b(&all_arguments_processed, EQ);
893 } 893 }
894 } 894 }
895 895
896 __ Bind(&wrong_num_arguments); 896 __ Bind(&wrong_num_arguments);
897 if (function.IsClosureFunction()) { 897 if (function.IsClosureFunction()) {
898 // Invoke noSuchMethod function passing "call" as the original name. 898 // Invoke noSuchMethod function passing "call" as the original name.
(...skipping 11 matching lines...) Expand all
910 } 910 }
911 911
912 __ Bind(&all_arguments_processed); 912 __ Bind(&all_arguments_processed);
913 // Nullify originally passed arguments only after they have been copied and 913 // Nullify originally passed arguments only after they have been copied and
914 // checked, otherwise noSuchMethod would not see their original values. 914 // checked, otherwise noSuchMethod would not see their original values.
915 // This step can be skipped in case we decide that formal parameters are 915 // This step can be skipped in case we decide that formal parameters are
916 // implicitly final, since garbage collecting the unmodified value is not 916 // implicitly final, since garbage collecting the unmodified value is not
917 // an issue anymore. 917 // an issue anymore.
918 918
919 // R4 : arguments descriptor array. 919 // R4 : arguments descriptor array.
920 __ LoadFieldFromOffset(R8, R4, ArgumentsDescriptor::count_offset()); 920 __ LoadFieldFromOffset(R8, R4, ArgumentsDescriptor::count_offset(), PP);
921 __ SmiUntag(R8); 921 __ SmiUntag(R8);
922 __ add(R7, FP, Operand((kParamEndSlotFromFp + 1) * kWordSize)); 922 __ add(R7, FP, Operand((kParamEndSlotFromFp + 1) * kWordSize));
923 const Address original_argument_addr(R7, R8, UXTX, Address::Scaled); 923 const Address original_argument_addr(R7, R8, UXTX, Address::Scaled);
924 __ LoadObject(TMP, Object::null_object(), PP); 924 __ LoadObject(TMP, Object::null_object(), PP);
925 Label null_args_loop, null_args_loop_condition; 925 Label null_args_loop, null_args_loop_condition;
926 __ b(&null_args_loop_condition); 926 __ b(&null_args_loop_condition);
927 __ Bind(&null_args_loop); 927 __ Bind(&null_args_loop);
928 __ str(TMP, original_argument_addr); 928 __ str(TMP, original_argument_addr);
929 __ Bind(&null_args_loop_condition); 929 __ Bind(&null_args_loop_condition);
930 __ subs(R8, R8, Operand(1)); 930 __ subs(R8, R8, Operand(1));
931 __ b(&null_args_loop, PL); 931 __ b(&null_args_loop, PL);
932 } 932 }
933 933
934 934
935 void FlowGraphCompiler::GenerateInlinedGetter(intptr_t offset) { 935 void FlowGraphCompiler::GenerateInlinedGetter(intptr_t offset) {
936 // LR: return address. 936 // LR: return address.
937 // SP: receiver. 937 // SP: receiver.
938 // Sequence node has one return node, its input is load field node. 938 // Sequence node has one return node, its input is load field node.
939 __ Comment("Inlined Getter"); 939 __ Comment("Inlined Getter");
940 __ LoadFromOffset(R0, SP, 0 * kWordSize); 940 __ LoadFromOffset(R0, SP, 0 * kWordSize, PP);
941 __ LoadFromOffset(R0, R0, offset - kHeapObjectTag); 941 __ LoadFromOffset(R0, R0, offset - kHeapObjectTag, PP);
942 __ ret(); 942 __ ret();
943 } 943 }
944 944
945 945
946 void FlowGraphCompiler::GenerateInlinedSetter(intptr_t offset) { 946 void FlowGraphCompiler::GenerateInlinedSetter(intptr_t offset) {
947 // LR: return address. 947 // LR: return address.
948 // SP+1: receiver. 948 // SP+1: receiver.
949 // SP+0: value. 949 // SP+0: value.
950 // Sequence node has one store node and one return NULL node. 950 // Sequence node has one store node and one return NULL node.
951 __ Comment("Inlined Setter"); 951 __ Comment("Inlined Setter");
952 __ LoadFromOffset(R0, SP, 1 * kWordSize); // Receiver. 952 __ LoadFromOffset(R0, SP, 1 * kWordSize, PP); // Receiver.
953 __ LoadFromOffset(R1, SP, 0 * kWordSize); // Value. 953 __ LoadFromOffset(R1, SP, 0 * kWordSize, PP); // Value.
954 __ StoreIntoObject(R0, FieldAddress(R0, offset), R1); 954 __ StoreIntoObjectOffset(R0, offset, R1, PP);
955 __ LoadObject(R0, Object::null_object(), PP); 955 __ LoadObject(R0, Object::null_object(), PP);
956 __ ret(); 956 __ ret();
957 } 957 }
958 958
959 959
960 void FlowGraphCompiler::EmitFrameEntry() { 960 void FlowGraphCompiler::EmitFrameEntry() {
961 const Function& function = parsed_function().function(); 961 const Function& function = parsed_function().function();
962 Register new_pp = kNoPP; 962 Register new_pp = kNoPP;
963 if (CanOptimizeFunction() && 963 if (CanOptimizeFunction() &&
964 function.IsOptimizable() && 964 function.IsOptimizable() &&
965 (!is_optimizing() || may_reoptimize())) { 965 (!is_optimizing() || may_reoptimize())) {
966 const Register function_reg = R6; 966 const Register function_reg = R6;
967 new_pp = R13; 967 new_pp = R13;
968 968
969 // Set up pool pointer in new_pp. 969 // Set up pool pointer in new_pp.
970 __ LoadPoolPointer(new_pp); 970 __ LoadPoolPointer(new_pp);
971 971
972 // Load function object using the callee's pool pointer. 972 // Load function object using the callee's pool pointer.
973 __ LoadObject(function_reg, function, new_pp); 973 __ LoadObject(function_reg, function, new_pp);
974 974
975 // Patch point is after the eventually inlined function object. 975 // Patch point is after the eventually inlined function object.
976 AddCurrentDescriptor(PcDescriptors::kEntryPatch, 976 AddCurrentDescriptor(PcDescriptors::kEntryPatch,
977 Isolate::kNoDeoptId, 977 Isolate::kNoDeoptId,
978 0); // No token position. 978 0); // No token position.
979 intptr_t threshold = FLAG_optimization_counter_threshold; 979 intptr_t threshold = FLAG_optimization_counter_threshold;
980 __ LoadFieldFromOffset(R7, function_reg, Function::usage_counter_offset()); 980 __ LoadFieldFromOffset(
981 R7, function_reg, Function::usage_counter_offset(), new_pp);
981 if (is_optimizing()) { 982 if (is_optimizing()) {
982 // Reoptimization of an optimized function is triggered by counting in 983 // Reoptimization of an optimized function is triggered by counting in
983 // IC stubs, but not at the entry of the function. 984 // IC stubs, but not at the entry of the function.
984 threshold = FLAG_reoptimization_counter_threshold; 985 threshold = FLAG_reoptimization_counter_threshold;
985 } else { 986 } else {
986 __ add(R7, R7, Operand(1)); 987 __ add(R7, R7, Operand(1));
987 __ StoreFieldToOffset(R7, function_reg, Function::usage_counter_offset()); 988 __ StoreFieldToOffset(
989 R7, function_reg, Function::usage_counter_offset(), new_pp);
988 } 990 }
989 __ CompareImmediate(R7, threshold, new_pp); 991 __ CompareImmediate(R7, threshold, new_pp);
990 ASSERT(function_reg == R6); 992 ASSERT(function_reg == R6);
991 Label dont_optimize; 993 Label dont_optimize;
992 __ b(&dont_optimize, LT); 994 __ b(&dont_optimize, LT);
993 __ Branch(&StubCode::OptimizeFunctionLabel(), new_pp); 995 __ Branch(&StubCode::OptimizeFunctionLabel(), new_pp);
994 __ Bind(&dont_optimize); 996 __ Bind(&dont_optimize);
995 } else if (!flow_graph().IsCompiledForOsr()) { 997 } else if (!flow_graph().IsCompiledForOsr()) {
996 // We have to load the PP here too because a load of an external label 998 // We have to load the PP here too because a load of an external label
997 // may be patched at the AddCurrentDescriptor below. 999 // may be patched at the AddCurrentDescriptor below.
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
1047 ASSERT(!parsed_function().function().HasOptionalParameters()); 1049 ASSERT(!parsed_function().function().HasOptionalParameters());
1048 const bool check_arguments = !flow_graph().IsCompiledForOsr(); 1050 const bool check_arguments = !flow_graph().IsCompiledForOsr();
1049 #else 1051 #else
1050 const bool check_arguments = 1052 const bool check_arguments =
1051 function.IsClosureFunction() && !flow_graph().IsCompiledForOsr(); 1053 function.IsClosureFunction() && !flow_graph().IsCompiledForOsr();
1052 #endif 1054 #endif
1053 if (check_arguments) { 1055 if (check_arguments) {
1054 __ Comment("Check argument count"); 1056 __ Comment("Check argument count");
1055 // Check that exactly num_fixed arguments are passed in. 1057 // Check that exactly num_fixed arguments are passed in.
1056 Label correct_num_arguments, wrong_num_arguments; 1058 Label correct_num_arguments, wrong_num_arguments;
1057 __ LoadFieldFromOffset(R0, R4, ArgumentsDescriptor::count_offset()); 1059 __ LoadFieldFromOffset(R0, R4, ArgumentsDescriptor::count_offset(), PP);
1058 __ CompareImmediate(R0, Smi::RawValue(num_fixed_params), PP); 1060 __ CompareImmediate(R0, Smi::RawValue(num_fixed_params), PP);
1059 __ b(&wrong_num_arguments, NE); 1061 __ b(&wrong_num_arguments, NE);
1060 __ LoadFieldFromOffset(R1, R4, 1062 __ LoadFieldFromOffset(R1, R4,
1061 ArgumentsDescriptor::positional_count_offset()); 1063 ArgumentsDescriptor::positional_count_offset(), PP);
1062 __ CompareRegisters(R0, R1); 1064 __ CompareRegisters(R0, R1);
1063 __ b(&correct_num_arguments, EQ); 1065 __ b(&correct_num_arguments, EQ);
1064 __ Bind(&wrong_num_arguments); 1066 __ Bind(&wrong_num_arguments);
1065 if (function.IsClosureFunction()) { 1067 if (function.IsClosureFunction()) {
1066 // Invoke noSuchMethod function passing the original function name. 1068 // Invoke noSuchMethod function passing the original function name.
1067 // For closure functions, use "call" as the original name. 1069 // For closure functions, use "call" as the original name.
1068 const String& name = 1070 const String& name =
1069 String::Handle(function.IsClosureFunction() 1071 String::Handle(function.IsClosureFunction()
1070 ? Symbols::Call().raw() 1072 ? Symbols::Call().raw()
1071 : function.name()); 1073 : function.name());
(...skipping 16 matching lines...) Expand all
1088 } 1090 }
1089 1091
1090 // In unoptimized code, initialize (non-argument) stack allocated slots to 1092 // In unoptimized code, initialize (non-argument) stack allocated slots to
1091 // null. 1093 // null.
1092 if (!is_optimizing() && (num_locals > 0)) { 1094 if (!is_optimizing() && (num_locals > 0)) {
1093 __ Comment("Initialize spill slots"); 1095 __ Comment("Initialize spill slots");
1094 const intptr_t slot_base = parsed_function().first_stack_local_index(); 1096 const intptr_t slot_base = parsed_function().first_stack_local_index();
1095 __ LoadObject(R0, Object::null_object(), PP); 1097 __ LoadObject(R0, Object::null_object(), PP);
1096 for (intptr_t i = 0; i < num_locals; ++i) { 1098 for (intptr_t i = 0; i < num_locals; ++i) {
1097 // Subtract index i (locals lie at lower addresses than FP). 1099 // Subtract index i (locals lie at lower addresses than FP).
1098 __ StoreToOffset(R0, FP, (slot_base - i) * kWordSize); 1100 __ StoreToOffset(R0, FP, (slot_base - i) * kWordSize, PP);
1099 } 1101 }
1100 } 1102 }
1101 1103
1102 VisitBlocks(); 1104 VisitBlocks();
1103 1105
1104 __ hlt(0); 1106 __ hlt(0);
1105 GenerateDeferredCode(); 1107 GenerateDeferredCode();
1106 // Emit function patching code. This will be swapped with the first 3 1108 // Emit function patching code. This will be swapped with the first 3
1107 // instructions at entry point. 1109 // instructions at entry point.
1108 AddCurrentDescriptor(PcDescriptors::kPatchCode, 1110 AddCurrentDescriptor(PcDescriptors::kPatchCode,
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
1176 void FlowGraphCompiler::EmitEdgeCounter() { 1178 void FlowGraphCompiler::EmitEdgeCounter() {
1177 // We do not check for overflow when incrementing the edge counter. The 1179 // We do not check for overflow when incrementing the edge counter. The
1178 // function should normally be optimized long before the counter can 1180 // function should normally be optimized long before the counter can
1179 // overflow; and though we do not reset the counters when we optimize or 1181 // overflow; and though we do not reset the counters when we optimize or
1180 // deoptimize, there is a bound on the number of 1182 // deoptimize, there is a bound on the number of
1181 // optimization/deoptimization cycles we will attempt. 1183 // optimization/deoptimization cycles we will attempt.
1182 const Array& counter = Array::ZoneHandle(Array::New(1, Heap::kOld)); 1184 const Array& counter = Array::ZoneHandle(Array::New(1, Heap::kOld));
1183 counter.SetAt(0, Smi::Handle(Smi::New(0))); 1185 counter.SetAt(0, Smi::Handle(Smi::New(0)));
1184 __ Comment("Edge counter"); 1186 __ Comment("Edge counter");
1185 __ LoadObject(R0, counter, PP); 1187 __ LoadObject(R0, counter, PP);
1186 __ LoadFieldFromOffset(TMP, R0, Array::element_offset(0)); 1188 __ LoadFieldFromOffset(TMP, R0, Array::element_offset(0), PP);
1187 __ add(TMP, TMP, Operand(Smi::RawValue(1))); 1189 __ add(TMP, TMP, Operand(Smi::RawValue(1)));
1188 __ StoreFieldToOffset(TMP, R0, Array::element_offset(0)); 1190 __ StoreFieldToOffset(TMP, R0, Array::element_offset(0), PP);
1189 } 1191 }
1190 1192
1191 1193
1192 void FlowGraphCompiler::EmitOptimizedInstanceCall( 1194 void FlowGraphCompiler::EmitOptimizedInstanceCall(
1193 ExternalLabel* target_label, 1195 ExternalLabel* target_label,
1194 const ICData& ic_data, 1196 const ICData& ic_data,
1195 intptr_t argument_count, 1197 intptr_t argument_count,
1196 intptr_t deopt_id, 1198 intptr_t deopt_id,
1197 intptr_t token_pos, 1199 intptr_t token_pos,
1198 LocationSummary* locs) { 1200 LocationSummary* locs) {
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
1239 intptr_t token_pos, 1241 intptr_t token_pos,
1240 LocationSummary* locs) { 1242 LocationSummary* locs) {
1241 MegamorphicCacheTable* table = Isolate::Current()->megamorphic_cache_table(); 1243 MegamorphicCacheTable* table = Isolate::Current()->megamorphic_cache_table();
1242 const String& name = String::Handle(ic_data.target_name()); 1244 const String& name = String::Handle(ic_data.target_name());
1243 const Array& arguments_descriptor = 1245 const Array& arguments_descriptor =
1244 Array::ZoneHandle(ic_data.arguments_descriptor()); 1246 Array::ZoneHandle(ic_data.arguments_descriptor());
1245 ASSERT(!arguments_descriptor.IsNull() && (arguments_descriptor.Length() > 0)); 1247 ASSERT(!arguments_descriptor.IsNull() && (arguments_descriptor.Length() > 0));
1246 const MegamorphicCache& cache = 1248 const MegamorphicCache& cache =
1247 MegamorphicCache::ZoneHandle(table->Lookup(name, arguments_descriptor)); 1249 MegamorphicCache::ZoneHandle(table->Lookup(name, arguments_descriptor));
1248 Label not_smi, load_cache; 1250 Label not_smi, load_cache;
1249 __ LoadFromOffset(R0, SP, (argument_count - 1) * kWordSize); 1251 __ LoadFromOffset(R0, SP, (argument_count - 1) * kWordSize, PP);
1250 __ tsti(R0, kSmiTagMask); 1252 __ tsti(R0, kSmiTagMask);
1251 __ b(&not_smi, NE); 1253 __ b(&not_smi, NE);
1252 __ LoadImmediate(R0, Smi::RawValue(kSmiCid), PP); 1254 __ LoadImmediate(R0, Smi::RawValue(kSmiCid), PP);
1253 __ b(&load_cache); 1255 __ b(&load_cache);
1254 1256
1255 __ Bind(&not_smi); 1257 __ Bind(&not_smi);
1256 __ LoadClassId(R0, R0); 1258 __ LoadClassId(R0, R0, PP);
1257 __ SmiTag(R0); 1259 __ SmiTag(R0);
1258 1260
1259 // R0: class ID of the receiver (smi). 1261 // R0: class ID of the receiver (smi).
1260 __ Bind(&load_cache); 1262 __ Bind(&load_cache);
1261 __ LoadObject(R1, cache, PP); 1263 __ LoadObject(R1, cache, PP);
1262 __ LoadFieldFromOffset(R2, R1, MegamorphicCache::buckets_offset()); 1264 __ LoadFieldFromOffset(R2, R1, MegamorphicCache::buckets_offset(), PP);
1263 __ LoadFieldFromOffset(R1, R1, MegamorphicCache::mask_offset()); 1265 __ LoadFieldFromOffset(R1, R1, MegamorphicCache::mask_offset(), PP);
1264 // R2: cache buckets array. 1266 // R2: cache buckets array.
1265 // R1: mask. 1267 // R1: mask.
1266 __ mov(R3, R0); 1268 __ mov(R3, R0);
1267 1269
1268 Label loop, update, call_target_function; 1270 Label loop, update, call_target_function;
1269 __ b(&loop); 1271 __ b(&loop);
1270 1272
1271 __ Bind(&update); 1273 __ Bind(&update);
1272 __ add(R3, R3, Operand(Smi::RawValue(1))); 1274 __ add(R3, R3, Operand(Smi::RawValue(1)));
1273 __ Bind(&loop); 1275 __ Bind(&loop);
1274 __ and_(R3, R3, Operand(R1)); 1276 __ and_(R3, R3, Operand(R1));
1275 const intptr_t base = Array::data_offset(); 1277 const intptr_t base = Array::data_offset();
1276 // R3 is smi tagged, but table entries are 8 bytes, so LSL 2. 1278 // R3 is smi tagged, but table entries are 8 bytes, so LSL 2.
1277 __ add(TMP, R2, Operand(R3, LSL, 2)); 1279 __ add(TMP, R2, Operand(R3, LSL, 2));
1278 __ LoadFieldFromOffset(R4, TMP, base); 1280 __ LoadFieldFromOffset(R4, TMP, base, PP);
1279 1281
1280 ASSERT(kIllegalCid == 0); 1282 ASSERT(kIllegalCid == 0);
1281 __ tst(R4, Operand(R4)); 1283 __ tst(R4, Operand(R4));
1282 __ b(&call_target_function, EQ); 1284 __ b(&call_target_function, EQ);
1283 __ CompareRegisters(R4, R0); 1285 __ CompareRegisters(R4, R0);
1284 __ b(&update, NE); 1286 __ b(&update, NE);
1285 1287
1286 __ Bind(&call_target_function); 1288 __ Bind(&call_target_function);
1287 // Call the target found in the cache. For a class id match, this is a 1289 // Call the target found in the cache. For a class id match, this is a
1288 // proper target for the given name and arguments descriptor. If the 1290 // proper target for the given name and arguments descriptor. If the
1289 // illegal class id was found, the target is a cache miss handler that can 1291 // illegal class id was found, the target is a cache miss handler that can
1290 // be invoked as a normal Dart function. 1292 // be invoked as a normal Dart function.
1291 __ add(TMP, R2, Operand(R3, LSL, 2)); 1293 __ add(TMP, R2, Operand(R3, LSL, 2));
1292 __ LoadFieldFromOffset(R0, TMP, base + kWordSize); 1294 __ LoadFieldFromOffset(R0, TMP, base + kWordSize, PP);
1293 __ LoadFieldFromOffset(R1, R0, Function::code_offset()); 1295 __ LoadFieldFromOffset(R1, R0, Function::code_offset(), PP);
1294 __ LoadFieldFromOffset(R1, R1, Code::instructions_offset()); 1296 __ LoadFieldFromOffset(R1, R1, Code::instructions_offset(), PP);
1295 __ LoadObject(R5, ic_data, PP); 1297 __ LoadObject(R5, ic_data, PP);
1296 __ LoadObject(R4, arguments_descriptor, PP); 1298 __ LoadObject(R4, arguments_descriptor, PP);
1297 __ AddImmediate(R1, R1, Instructions::HeaderSize() - kHeapObjectTag, PP); 1299 __ AddImmediate(R1, R1, Instructions::HeaderSize() - kHeapObjectTag, PP);
1298 __ blr(R1); 1300 __ blr(R1);
1299 AddCurrentDescriptor(PcDescriptors::kOther, Isolate::kNoDeoptId, token_pos); 1301 AddCurrentDescriptor(PcDescriptors::kOther, Isolate::kNoDeoptId, token_pos);
1300 RecordSafepoint(locs); 1302 RecordSafepoint(locs);
1301 AddDeoptIndexAtCall(Isolate::ToDeoptAfter(deopt_id), token_pos); 1303 AddDeoptIndexAtCall(Isolate::ToDeoptAfter(deopt_id), token_pos);
1302 __ Drop(argument_count); 1304 __ Drop(argument_count);
1303 } 1305 }
1304 1306
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after
1568 MoveOperands* move = moves_[index]; 1570 MoveOperands* move = moves_[index];
1569 const Location source = move->src(); 1571 const Location source = move->src();
1570 const Location destination = move->dest(); 1572 const Location destination = move->dest();
1571 1573
1572 if (source.IsRegister()) { 1574 if (source.IsRegister()) {
1573 if (destination.IsRegister()) { 1575 if (destination.IsRegister()) {
1574 __ mov(destination.reg(), source.reg()); 1576 __ mov(destination.reg(), source.reg());
1575 } else { 1577 } else {
1576 ASSERT(destination.IsStackSlot()); 1578 ASSERT(destination.IsStackSlot());
1577 const intptr_t dest_offset = destination.ToStackSlotOffset(); 1579 const intptr_t dest_offset = destination.ToStackSlotOffset();
1578 __ StoreToOffset(source.reg(), FP, dest_offset); 1580 __ StoreToOffset(source.reg(), FP, dest_offset, PP);
1579 } 1581 }
1580 } else if (source.IsStackSlot()) { 1582 } else if (source.IsStackSlot()) {
1581 if (destination.IsRegister()) { 1583 if (destination.IsRegister()) {
1582 const intptr_t source_offset = source.ToStackSlotOffset(); 1584 const intptr_t source_offset = source.ToStackSlotOffset();
1583 __ LoadFromOffset(destination.reg(), FP, source_offset); 1585 __ LoadFromOffset(destination.reg(), FP, source_offset, PP);
1584 } else { 1586 } else {
1585 ASSERT(destination.IsStackSlot()); 1587 ASSERT(destination.IsStackSlot());
1586 const intptr_t source_offset = source.ToStackSlotOffset(); 1588 const intptr_t source_offset = source.ToStackSlotOffset();
1587 const intptr_t dest_offset = destination.ToStackSlotOffset(); 1589 const intptr_t dest_offset = destination.ToStackSlotOffset();
1588 __ LoadFromOffset(TMP, FP, source_offset); 1590 __ LoadFromOffset(TMP, FP, source_offset, PP);
1589 __ StoreToOffset(TMP, FP, dest_offset); 1591 __ StoreToOffset(TMP, FP, dest_offset, PP);
1590 } 1592 }
1591 } else if (source.IsFpuRegister()) { 1593 } else if (source.IsFpuRegister()) {
1592 if (destination.IsFpuRegister()) { 1594 if (destination.IsFpuRegister()) {
1593 __ fmovdd(destination.fpu_reg(), source.fpu_reg()); 1595 __ fmovdd(destination.fpu_reg(), source.fpu_reg());
1594 } else { 1596 } else {
1595 if (destination.IsDoubleStackSlot()) { 1597 if (destination.IsDoubleStackSlot()) {
1596 const intptr_t dest_offset = destination.ToStackSlotOffset(); 1598 const intptr_t dest_offset = destination.ToStackSlotOffset();
1597 VRegister src = source.fpu_reg(); 1599 VRegister src = source.fpu_reg();
1598 __ StoreDToOffset(src, FP, dest_offset); 1600 __ StoreDToOffset(src, FP, dest_offset, PP);
1599 } else { 1601 } else {
1600 ASSERT(destination.IsQuadStackSlot()); 1602 ASSERT(destination.IsQuadStackSlot());
1601 UNIMPLEMENTED(); 1603 UNIMPLEMENTED();
1602 } 1604 }
1603 } 1605 }
1604 } else if (source.IsDoubleStackSlot()) { 1606 } else if (source.IsDoubleStackSlot()) {
1605 if (destination.IsFpuRegister()) { 1607 if (destination.IsFpuRegister()) {
1606 const intptr_t dest_offset = source.ToStackSlotOffset(); 1608 const intptr_t dest_offset = source.ToStackSlotOffset();
1607 const VRegister dst = destination.fpu_reg(); 1609 const VRegister dst = destination.fpu_reg();
1608 __ LoadDFromOffset(dst, FP, dest_offset); 1610 __ LoadDFromOffset(dst, FP, dest_offset, PP);
1609 } else { 1611 } else {
1610 ASSERT(destination.IsDoubleStackSlot()); 1612 ASSERT(destination.IsDoubleStackSlot());
1611 const intptr_t source_offset = source.ToStackSlotOffset(); 1613 const intptr_t source_offset = source.ToStackSlotOffset();
1612 const intptr_t dest_offset = destination.ToStackSlotOffset(); 1614 const intptr_t dest_offset = destination.ToStackSlotOffset();
1613 __ LoadDFromOffset(VTMP, FP, source_offset); 1615 __ LoadDFromOffset(VTMP, FP, source_offset, PP);
1614 __ StoreDToOffset(VTMP, FP, dest_offset); 1616 __ StoreDToOffset(VTMP, FP, dest_offset, PP);
1615 } 1617 }
1616 } else if (source.IsQuadStackSlot()) { 1618 } else if (source.IsQuadStackSlot()) {
1617 UNIMPLEMENTED(); 1619 UNIMPLEMENTED();
1618 } else { 1620 } else {
1619 ASSERT(source.IsConstant()); 1621 ASSERT(source.IsConstant());
1620 const Object& constant = source.constant(); 1622 const Object& constant = source.constant();
1621 if (destination.IsRegister()) { 1623 if (destination.IsRegister()) {
1622 __ LoadObject(destination.reg(), constant, PP); 1624 __ LoadObject(destination.reg(), constant, PP);
1623 } else if (destination.IsFpuRegister()) { 1625 } else if (destination.IsFpuRegister()) {
1624 const VRegister dst = destination.fpu_reg(); 1626 const VRegister dst = destination.fpu_reg();
1625 __ LoadObject(TMP, constant, PP); 1627 __ LoadObject(TMP, constant, PP);
1626 __ LoadDFieldFromOffset(dst, TMP, Double::value_offset()); 1628 __ LoadDFieldFromOffset(dst, TMP, Double::value_offset(), PP);
1627 } else if (destination.IsDoubleStackSlot()) { 1629 } else if (destination.IsDoubleStackSlot()) {
1628 const intptr_t dest_offset = destination.ToStackSlotOffset(); 1630 const intptr_t dest_offset = destination.ToStackSlotOffset();
1629 __ LoadObject(TMP, constant, PP); 1631 __ LoadObject(TMP, constant, PP);
1630 __ LoadDFieldFromOffset(VTMP, TMP, Double::value_offset()); 1632 __ LoadDFieldFromOffset(VTMP, TMP, Double::value_offset(), PP);
1631 __ StoreDToOffset(VTMP, FP, dest_offset); 1633 __ StoreDToOffset(VTMP, FP, dest_offset, PP);
1632 } else { 1634 } else {
1633 ASSERT(destination.IsStackSlot()); 1635 ASSERT(destination.IsStackSlot());
1634 const intptr_t dest_offset = destination.ToStackSlotOffset(); 1636 const intptr_t dest_offset = destination.ToStackSlotOffset();
1635 __ LoadObject(TMP, constant, PP); 1637 __ LoadObject(TMP, constant, PP);
1636 __ StoreToOffset(TMP, FP, dest_offset); 1638 __ StoreToOffset(TMP, FP, dest_offset, PP);
1637 } 1639 }
1638 } 1640 }
1639 1641
1640 move->Eliminate(); 1642 move->Eliminate();
1641 } 1643 }
1642 1644
1643 1645
1644 void ParallelMoveResolver::EmitSwap(int index) { 1646 void ParallelMoveResolver::EmitSwap(int index) {
1645 MoveOperands* move = moves_[index]; 1647 MoveOperands* move = moves_[index];
1646 const Location source = move->src(); 1648 const Location source = move->src();
(...skipping 24 matching lines...) Expand all
1671 source.IsQuadStackSlot()); 1673 source.IsQuadStackSlot());
1672 bool double_width = destination.IsDoubleStackSlot() || 1674 bool double_width = destination.IsDoubleStackSlot() ||
1673 source.IsDoubleStackSlot(); 1675 source.IsDoubleStackSlot();
1674 VRegister reg = source.IsFpuRegister() ? source.fpu_reg() 1676 VRegister reg = source.IsFpuRegister() ? source.fpu_reg()
1675 : destination.fpu_reg(); 1677 : destination.fpu_reg();
1676 const intptr_t slot_offset = source.IsFpuRegister() 1678 const intptr_t slot_offset = source.IsFpuRegister()
1677 ? destination.ToStackSlotOffset() 1679 ? destination.ToStackSlotOffset()
1678 : source.ToStackSlotOffset(); 1680 : source.ToStackSlotOffset();
1679 1681
1680 if (double_width) { 1682 if (double_width) {
1681 __ LoadDFromOffset(VTMP, FP, slot_offset); 1683 __ LoadDFromOffset(VTMP, FP, slot_offset, PP);
1682 __ StoreDToOffset(reg, FP, slot_offset); 1684 __ StoreDToOffset(reg, FP, slot_offset, PP);
1683 __ fmovdd(reg, VTMP); 1685 __ fmovdd(reg, VTMP);
1684 } else { 1686 } else {
1685 UNIMPLEMENTED(); 1687 UNIMPLEMENTED();
1686 } 1688 }
1687 } else if (source.IsDoubleStackSlot() && destination.IsDoubleStackSlot()) { 1689 } else if (source.IsDoubleStackSlot() && destination.IsDoubleStackSlot()) {
1688 const intptr_t source_offset = source.ToStackSlotOffset(); 1690 const intptr_t source_offset = source.ToStackSlotOffset();
1689 const intptr_t dest_offset = destination.ToStackSlotOffset(); 1691 const intptr_t dest_offset = destination.ToStackSlotOffset();
1690 1692
1691 ScratchFpuRegisterScope ensure_scratch(this, VTMP); 1693 ScratchFpuRegisterScope ensure_scratch(this, VTMP);
1692 VRegister scratch = ensure_scratch.reg(); 1694 VRegister scratch = ensure_scratch.reg();
1693 __ LoadDFromOffset(VTMP, FP, source_offset); 1695 __ LoadDFromOffset(VTMP, FP, source_offset, PP);
1694 __ LoadDFromOffset(scratch, FP, dest_offset); 1696 __ LoadDFromOffset(scratch, FP, dest_offset, PP);
1695 __ StoreDToOffset(VTMP, FP, dest_offset); 1697 __ StoreDToOffset(VTMP, FP, dest_offset, PP);
1696 __ StoreDToOffset(scratch, FP, source_offset); 1698 __ StoreDToOffset(scratch, FP, source_offset, PP);
1697 } else if (source.IsQuadStackSlot() && destination.IsQuadStackSlot()) { 1699 } else if (source.IsQuadStackSlot() && destination.IsQuadStackSlot()) {
1698 UNIMPLEMENTED(); 1700 UNIMPLEMENTED();
1699 } else { 1701 } else {
1700 UNREACHABLE(); 1702 UNREACHABLE();
1701 } 1703 }
1702 1704
1703 // The swap of source and destination has executed a move from source to 1705 // The swap of source and destination has executed a move from source to
1704 // destination. 1706 // destination.
1705 move->Eliminate(); 1707 move->Eliminate();
1706 1708
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
1772 void ParallelMoveResolver::RestoreFpuScratch(FpuRegister reg) { 1774 void ParallelMoveResolver::RestoreFpuScratch(FpuRegister reg) {
1773 UNIMPLEMENTED(); 1775 UNIMPLEMENTED();
1774 } 1776 }
1775 1777
1776 1778
1777 #undef __ 1779 #undef __
1778 1780
1779 } // namespace dart 1781 } // namespace dart
1780 1782
1781 #endif // defined TARGET_ARCH_ARM64 1783 #endif // defined TARGET_ARCH_ARM64
OLDNEW
« no previous file with comments | « runtime/vm/disassembler_arm64.cc ('k') | runtime/vm/intermediate_language_arm64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698