| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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_ARM. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM. |
| 6 #if defined(TARGET_ARCH_ARM) | 6 #if defined(TARGET_ARCH_ARM) |
| 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 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 60 | 60 |
| 61 | 61 |
| 62 bool FlowGraphCompiler::SupportsHardwareDivision() { | 62 bool FlowGraphCompiler::SupportsHardwareDivision() { |
| 63 return TargetCPUFeatures::can_divide(); | 63 return TargetCPUFeatures::can_divide(); |
| 64 } | 64 } |
| 65 | 65 |
| 66 | 66 |
| 67 void FlowGraphCompiler::EnterIntrinsicMode() { | 67 void FlowGraphCompiler::EnterIntrinsicMode() { |
| 68 ASSERT(!intrinsic_mode()); | 68 ASSERT(!intrinsic_mode()); |
| 69 intrinsic_mode_ = true; | 69 intrinsic_mode_ = true; |
| 70 assembler()->set_constant_pool_allowed(false); | 70 ASSERT(!assembler()->constant_pool_allowed()); |
| 71 } | 71 } |
| 72 | 72 |
| 73 | 73 |
| 74 void FlowGraphCompiler::ExitIntrinsicMode() { | 74 void FlowGraphCompiler::ExitIntrinsicMode() { |
| 75 ASSERT(intrinsic_mode()); | 75 ASSERT(intrinsic_mode()); |
| 76 intrinsic_mode_ = false; | 76 intrinsic_mode_ = false; |
| 77 assembler()->set_constant_pool_allowed(true); | |
| 78 } | 77 } |
| 79 | 78 |
| 80 | 79 |
| 81 RawTypedData* CompilerDeoptInfo::CreateDeoptInfo(FlowGraphCompiler* compiler, | 80 RawTypedData* CompilerDeoptInfo::CreateDeoptInfo(FlowGraphCompiler* compiler, |
| 82 DeoptInfoBuilder* builder, | 81 DeoptInfoBuilder* builder, |
| 83 const Array& deopt_table) { | 82 const Array& deopt_table) { |
| 84 if (deopt_env_ == NULL) { | 83 if (deopt_env_ == NULL) { |
| 85 ++builder->current_info_number_; | 84 ++builder->current_info_number_; |
| 86 return TypedData::null(); | 85 return TypedData::null(); |
| 87 } | 86 } |
| (...skipping 825 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 913 __ ldr(R7, FieldAddress(R4, ArgumentsDescriptor::count_offset())); | 912 __ ldr(R7, FieldAddress(R4, ArgumentsDescriptor::count_offset())); |
| 914 __ SmiUntag(R7); | 913 __ SmiUntag(R7); |
| 915 // Check that R9 equals R7, i.e. no named arguments passed. | 914 // Check that R9 equals R7, i.e. no named arguments passed. |
| 916 __ cmp(R9, Operand(R7)); | 915 __ cmp(R9, Operand(R7)); |
| 917 __ b(&all_arguments_processed, EQ); | 916 __ b(&all_arguments_processed, EQ); |
| 918 } | 917 } |
| 919 } | 918 } |
| 920 | 919 |
| 921 __ Bind(&wrong_num_arguments); | 920 __ Bind(&wrong_num_arguments); |
| 922 if (function.IsClosureFunction()) { | 921 if (function.IsClosureFunction()) { |
| 922 ASSERT(assembler()->constant_pool_allowed()); |
| 923 __ LeaveDartFrame(); // The arguments are still on the stack. | 923 __ LeaveDartFrame(); // The arguments are still on the stack. |
| 924 // Do not use caller's pool ptr in branch. |
| 925 ASSERT(!assembler()->constant_pool_allowed()); |
| 924 __ Branch(&StubCode::CallClosureNoSuchMethodLabel()); | 926 __ Branch(&StubCode::CallClosureNoSuchMethodLabel()); |
| 927 __ set_constant_pool_allowed(true); |
| 925 // The noSuchMethod call may return to the caller, but not here. | 928 // The noSuchMethod call may return to the caller, but not here. |
| 926 } else if (check_correct_named_args) { | 929 } else if (check_correct_named_args) { |
| 927 __ Stop("Wrong arguments"); | 930 __ Stop("Wrong arguments"); |
| 928 } | 931 } |
| 929 | 932 |
| 930 __ Bind(&all_arguments_processed); | 933 __ Bind(&all_arguments_processed); |
| 931 // Nullify originally passed arguments only after they have been copied and | 934 // Nullify originally passed arguments only after they have been copied and |
| 932 // checked, otherwise noSuchMethod would not see their original values. | 935 // checked, otherwise noSuchMethod would not see their original values. |
| 933 // This step can be skipped in case we decide that formal parameters are | 936 // This step can be skipped in case we decide that formal parameters are |
| 934 // implicitly final, since garbage collecting the unmodified value is not | 937 // implicitly final, since garbage collecting the unmodified value is not |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 984 | 987 |
| 985 // The pool pointer is not setup before entering the Dart frame. | 988 // The pool pointer is not setup before entering the Dart frame. |
| 986 // Preserve PP of caller. | 989 // Preserve PP of caller. |
| 987 __ mov(R7, Operand(PP)); | 990 __ mov(R7, Operand(PP)); |
| 988 // Temporarily setup pool pointer for this dart function. | 991 // Temporarily setup pool pointer for this dart function. |
| 989 __ LoadPoolPointer(); | 992 __ LoadPoolPointer(); |
| 990 // Load function object from object pool. | 993 // Load function object from object pool. |
| 991 __ LoadObject(function_reg, function); // Uses PP. | 994 __ LoadObject(function_reg, function); // Uses PP. |
| 992 // Restore PP of caller. | 995 // Restore PP of caller. |
| 993 __ mov(PP, Operand(R7)); | 996 __ mov(PP, Operand(R7)); |
| 997 __ set_constant_pool_allowed(false); |
| 994 | 998 |
| 995 // Patch point is after the eventually inlined function object. | 999 // Patch point is after the eventually inlined function object. |
| 996 entry_patch_pc_offset_ = assembler()->CodeSize(); | 1000 entry_patch_pc_offset_ = assembler()->CodeSize(); |
| 997 | 1001 |
| 998 __ ldr(R7, FieldAddress(function_reg, | 1002 __ ldr(R7, FieldAddress(function_reg, |
| 999 Function::usage_counter_offset())); | 1003 Function::usage_counter_offset())); |
| 1000 // Reoptimization of an optimized function is triggered by counting in | 1004 // Reoptimization of an optimized function is triggered by counting in |
| 1001 // IC stubs, but not at the entry of the function. | 1005 // IC stubs, but not at the entry of the function. |
| 1002 if (!is_optimizing()) { | 1006 if (!is_optimizing()) { |
| 1003 __ add(R7, R7, Operand(1)); | 1007 __ add(R7, R7, Operand(1)); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 1030 // FP: caller's frame pointer. | 1034 // FP: caller's frame pointer. |
| 1031 // PP: caller's pool pointer. | 1035 // PP: caller's pool pointer. |
| 1032 // R5: ic-data. | 1036 // R5: ic-data. |
| 1033 // R4: arguments descriptor array. | 1037 // R4: arguments descriptor array. |
| 1034 void FlowGraphCompiler::CompileGraph() { | 1038 void FlowGraphCompiler::CompileGraph() { |
| 1035 InitCompiler(); | 1039 InitCompiler(); |
| 1036 | 1040 |
| 1037 TryIntrinsify(); | 1041 TryIntrinsify(); |
| 1038 | 1042 |
| 1039 EmitFrameEntry(); | 1043 EmitFrameEntry(); |
| 1044 ASSERT(assembler()->constant_pool_allowed()); |
| 1040 | 1045 |
| 1041 const Function& function = parsed_function().function(); | 1046 const Function& function = parsed_function().function(); |
| 1042 | 1047 |
| 1043 const int num_fixed_params = function.num_fixed_parameters(); | 1048 const int num_fixed_params = function.num_fixed_parameters(); |
| 1044 const int num_copied_params = parsed_function().num_copied_params(); | 1049 const int num_copied_params = parsed_function().num_copied_params(); |
| 1045 const int num_locals = parsed_function().num_stack_locals(); | 1050 const int num_locals = parsed_function().num_stack_locals(); |
| 1046 | 1051 |
| 1047 // We check the number of passed arguments when we have to copy them due to | 1052 // We check the number of passed arguments when we have to copy them due to |
| 1048 // the presence of optional parameters. | 1053 // the presence of optional parameters. |
| 1049 // No such checking code is generated if only fixed parameters are declared, | 1054 // No such checking code is generated if only fixed parameters are declared, |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1062 Label correct_num_arguments, wrong_num_arguments; | 1067 Label correct_num_arguments, wrong_num_arguments; |
| 1063 __ ldr(R0, FieldAddress(R4, ArgumentsDescriptor::count_offset())); | 1068 __ ldr(R0, FieldAddress(R4, ArgumentsDescriptor::count_offset())); |
| 1064 __ CompareImmediate(R0, Smi::RawValue(num_fixed_params)); | 1069 __ CompareImmediate(R0, Smi::RawValue(num_fixed_params)); |
| 1065 __ b(&wrong_num_arguments, NE); | 1070 __ b(&wrong_num_arguments, NE); |
| 1066 __ ldr(R1, FieldAddress(R4, | 1071 __ ldr(R1, FieldAddress(R4, |
| 1067 ArgumentsDescriptor::positional_count_offset())); | 1072 ArgumentsDescriptor::positional_count_offset())); |
| 1068 __ cmp(R0, Operand(R1)); | 1073 __ cmp(R0, Operand(R1)); |
| 1069 __ b(&correct_num_arguments, EQ); | 1074 __ b(&correct_num_arguments, EQ); |
| 1070 __ Bind(&wrong_num_arguments); | 1075 __ Bind(&wrong_num_arguments); |
| 1071 if (function.IsClosureFunction()) { | 1076 if (function.IsClosureFunction()) { |
| 1077 ASSERT(assembler()->constant_pool_allowed()); |
| 1072 __ LeaveDartFrame(); // The arguments are still on the stack. | 1078 __ LeaveDartFrame(); // The arguments are still on the stack. |
| 1079 // Do not use caller's pool ptr in branch. |
| 1080 ASSERT(!assembler()->constant_pool_allowed()); |
| 1073 __ Branch(&StubCode::CallClosureNoSuchMethodLabel()); | 1081 __ Branch(&StubCode::CallClosureNoSuchMethodLabel()); |
| 1082 __ set_constant_pool_allowed(true); |
| 1074 // The noSuchMethod call may return to the caller, but not here. | 1083 // The noSuchMethod call may return to the caller, but not here. |
| 1075 } else { | 1084 } else { |
| 1076 __ Stop("Wrong number of arguments"); | 1085 __ Stop("Wrong number of arguments"); |
| 1077 } | 1086 } |
| 1078 __ Bind(&correct_num_arguments); | 1087 __ Bind(&correct_num_arguments); |
| 1079 } | 1088 } |
| 1080 } else if (!flow_graph().IsCompiledForOsr()) { | 1089 } else if (!flow_graph().IsCompiledForOsr()) { |
| 1081 CopyParameters(); | 1090 CopyParameters(); |
| 1082 } | 1091 } |
| 1083 | 1092 |
| (...skipping 30 matching lines...) Expand all Loading... |
| 1114 } else { | 1123 } else { |
| 1115 ASSERT(num_locals > 1); | 1124 ASSERT(num_locals > 1); |
| 1116 __ StoreToOffset(kWord, R0, FP, (slot_base - i) * kWordSize); | 1125 __ StoreToOffset(kWord, R0, FP, (slot_base - i) * kWordSize); |
| 1117 } | 1126 } |
| 1118 } | 1127 } |
| 1119 } | 1128 } |
| 1120 | 1129 |
| 1121 VisitBlocks(); | 1130 VisitBlocks(); |
| 1122 | 1131 |
| 1123 __ bkpt(0); | 1132 __ bkpt(0); |
| 1133 ASSERT(assembler()->constant_pool_allowed()); |
| 1124 GenerateDeferredCode(); | 1134 GenerateDeferredCode(); |
| 1125 // Emit function patching code. This will be swapped with the first 3 | 1135 // Emit function patching code. This will be swapped with the first 3 |
| 1126 // instructions at entry point. | 1136 // instructions at entry point. |
| 1127 patch_code_pc_offset_ = assembler()->CodeSize(); | 1137 patch_code_pc_offset_ = assembler()->CodeSize(); |
| 1128 __ BranchPatchable(&StubCode::FixCallersTargetLabel()); | 1138 __ BranchPatchable(&StubCode::FixCallersTargetLabel()); |
| 1129 | 1139 |
| 1130 if (is_optimizing()) { | 1140 if (is_optimizing()) { |
| 1131 lazy_deopt_pc_offset_ = assembler()->CodeSize(); | 1141 lazy_deopt_pc_offset_ = assembler()->CodeSize(); |
| 1132 __ Branch(&StubCode::DeoptimizeLazyLabel()); | 1142 __ Branch(&StubCode::DeoptimizeLazyLabel()); |
| 1133 } | 1143 } |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1190 } | 1200 } |
| 1191 } | 1201 } |
| 1192 | 1202 |
| 1193 | 1203 |
| 1194 void FlowGraphCompiler::EmitEdgeCounter() { | 1204 void FlowGraphCompiler::EmitEdgeCounter() { |
| 1195 // We do not check for overflow when incrementing the edge counter. The | 1205 // We do not check for overflow when incrementing the edge counter. The |
| 1196 // function should normally be optimized long before the counter can | 1206 // function should normally be optimized long before the counter can |
| 1197 // overflow; and though we do not reset the counters when we optimize or | 1207 // overflow; and though we do not reset the counters when we optimize or |
| 1198 // deoptimize, there is a bound on the number of | 1208 // deoptimize, there is a bound on the number of |
| 1199 // optimization/deoptimization cycles we will attempt. | 1209 // optimization/deoptimization cycles we will attempt. |
| 1210 ASSERT(assembler_->constant_pool_allowed()); |
| 1200 const Array& counter = Array::ZoneHandle(Array::New(1, Heap::kOld)); | 1211 const Array& counter = Array::ZoneHandle(Array::New(1, Heap::kOld)); |
| 1201 counter.SetAt(0, Smi::Handle(Smi::New(0))); | 1212 counter.SetAt(0, Smi::Handle(Smi::New(0))); |
| 1202 __ Comment("Edge counter"); | 1213 __ Comment("Edge counter"); |
| 1203 __ LoadUniqueObject(R0, counter); | 1214 __ LoadUniqueObject(R0, counter); |
| 1204 intptr_t increment_start = assembler_->CodeSize(); | 1215 intptr_t increment_start = assembler_->CodeSize(); |
| 1205 #if defined(DEBUG) | 1216 #if defined(DEBUG) |
| 1206 bool old_use_far_branches = assembler_->use_far_branches(); | 1217 bool old_use_far_branches = assembler_->use_far_branches(); |
| 1207 assembler_->set_use_far_branches(true); | 1218 assembler_->set_use_far_branches(true); |
| 1208 #endif // DEBUG | 1219 #endif // DEBUG |
| 1209 __ ldr(IP, FieldAddress(R0, Array::element_offset(0))); | 1220 __ ldr(IP, FieldAddress(R0, Array::element_offset(0))); |
| (...skipping 679 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1889 DRegister dreg = EvenDRegisterOf(reg); | 1900 DRegister dreg = EvenDRegisterOf(reg); |
| 1890 __ vldrd(dreg, Address(SP, kDoubleSize, Address::PostIndex)); | 1901 __ vldrd(dreg, Address(SP, kDoubleSize, Address::PostIndex)); |
| 1891 } | 1902 } |
| 1892 | 1903 |
| 1893 | 1904 |
| 1894 #undef __ | 1905 #undef __ |
| 1895 | 1906 |
| 1896 } // namespace dart | 1907 } // namespace dart |
| 1897 | 1908 |
| 1898 #endif // defined TARGET_ARCH_ARM | 1909 #endif // defined TARGET_ARCH_ARM |
| OLD | NEW |