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_X64. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. |
6 #if defined(TARGET_ARCH_X64) | 6 #if defined(TARGET_ARCH_X64) |
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 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
182 Assembler* assem = compiler->assembler(); | 182 Assembler* assem = compiler->assembler(); |
183 #define __ assem-> | 183 #define __ assem-> |
184 __ Comment("%s", Name()); | 184 __ Comment("%s", Name()); |
185 __ Bind(entry_label()); | 185 __ Bind(entry_label()); |
186 if (FLAG_trap_on_deoptimization) { | 186 if (FLAG_trap_on_deoptimization) { |
187 __ int3(); | 187 __ int3(); |
188 } | 188 } |
189 | 189 |
190 ASSERT(deopt_env() != NULL); | 190 ASSERT(deopt_env() != NULL); |
191 | 191 |
192 StubCode* stub_code = compiler->isolate()->stub_code(); | 192 __ Call(&StubCode::DeoptimizeLabel(), PP); |
193 __ Call(&stub_code->DeoptimizeLabel(), PP); | |
194 set_pc_offset(assem->CodeSize()); | 193 set_pc_offset(assem->CodeSize()); |
195 __ int3(); | 194 __ int3(); |
196 #undef __ | 195 #undef __ |
197 } | 196 } |
198 | 197 |
199 | 198 |
200 #define __ assembler()-> | 199 #define __ assembler()-> |
201 | 200 |
202 | 201 |
203 // Fall through if bool_register contains null. | 202 // Fall through if bool_register contains null. |
(...skipping 13 matching lines...) Expand all Loading... |
217 // Clobbers RCX. | 216 // Clobbers RCX. |
218 RawSubtypeTestCache* FlowGraphCompiler::GenerateCallSubtypeTestStub( | 217 RawSubtypeTestCache* FlowGraphCompiler::GenerateCallSubtypeTestStub( |
219 TypeTestStubKind test_kind, | 218 TypeTestStubKind test_kind, |
220 Register instance_reg, | 219 Register instance_reg, |
221 Register type_arguments_reg, | 220 Register type_arguments_reg, |
222 Register temp_reg, | 221 Register temp_reg, |
223 Label* is_instance_lbl, | 222 Label* is_instance_lbl, |
224 Label* is_not_instance_lbl) { | 223 Label* is_not_instance_lbl) { |
225 const SubtypeTestCache& type_test_cache = | 224 const SubtypeTestCache& type_test_cache = |
226 SubtypeTestCache::ZoneHandle(SubtypeTestCache::New()); | 225 SubtypeTestCache::ZoneHandle(SubtypeTestCache::New()); |
227 StubCode* stub_code = isolate()->stub_code(); | |
228 __ LoadUniqueObject(temp_reg, type_test_cache, PP); | 226 __ LoadUniqueObject(temp_reg, type_test_cache, PP); |
229 __ pushq(temp_reg); // Subtype test cache. | 227 __ pushq(temp_reg); // Subtype test cache. |
230 __ pushq(instance_reg); // Instance. | 228 __ pushq(instance_reg); // Instance. |
231 if (test_kind == kTestTypeOneArg) { | 229 if (test_kind == kTestTypeOneArg) { |
232 ASSERT(type_arguments_reg == kNoRegister); | 230 ASSERT(type_arguments_reg == kNoRegister); |
233 __ PushObject(Object::null_object(), PP); | 231 __ PushObject(Object::null_object(), PP); |
234 __ Call(&stub_code->Subtype1TestCacheLabel(), PP); | 232 __ Call(&StubCode::Subtype1TestCacheLabel(), PP); |
235 } else if (test_kind == kTestTypeTwoArgs) { | 233 } else if (test_kind == kTestTypeTwoArgs) { |
236 ASSERT(type_arguments_reg == kNoRegister); | 234 ASSERT(type_arguments_reg == kNoRegister); |
237 __ PushObject(Object::null_object(), PP); | 235 __ PushObject(Object::null_object(), PP); |
238 __ Call(&stub_code->Subtype2TestCacheLabel(), PP); | 236 __ Call(&StubCode::Subtype2TestCacheLabel(), PP); |
239 } else if (test_kind == kTestTypeThreeArgs) { | 237 } else if (test_kind == kTestTypeThreeArgs) { |
240 __ pushq(type_arguments_reg); | 238 __ pushq(type_arguments_reg); |
241 __ Call(&stub_code->Subtype3TestCacheLabel(), PP); | 239 __ Call(&StubCode::Subtype3TestCacheLabel(), PP); |
242 } else { | 240 } else { |
243 UNREACHABLE(); | 241 UNREACHABLE(); |
244 } | 242 } |
245 // Result is in RCX: null -> not found, otherwise Bool::True or Bool::False. | 243 // Result is in RCX: null -> not found, otherwise Bool::True or Bool::False. |
246 ASSERT(instance_reg != RCX); | 244 ASSERT(instance_reg != RCX); |
247 ASSERT(temp_reg != RCX); | 245 ASSERT(temp_reg != RCX); |
248 __ popq(instance_reg); // Discard. | 246 __ popq(instance_reg); // Discard. |
249 __ popq(instance_reg); // Restore receiver. | 247 __ popq(instance_reg); // Restore receiver. |
250 __ popq(temp_reg); // Discard. | 248 __ popq(temp_reg); // Discard. |
251 GenerateBoolToJump(RCX, is_instance_lbl, is_not_instance_lbl); | 249 GenerateBoolToJump(RCX, is_instance_lbl, is_not_instance_lbl); |
(...skipping 673 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
925 __ SmiUntag(RBX); | 923 __ SmiUntag(RBX); |
926 // Check that RCX equals RBX, i.e. no named arguments passed. | 924 // Check that RCX equals RBX, i.e. no named arguments passed. |
927 __ cmpq(RCX, RBX); | 925 __ cmpq(RCX, RBX); |
928 __ j(EQUAL, &all_arguments_processed, Assembler::kNearJump); | 926 __ j(EQUAL, &all_arguments_processed, Assembler::kNearJump); |
929 } | 927 } |
930 } | 928 } |
931 | 929 |
932 __ Bind(&wrong_num_arguments); | 930 __ Bind(&wrong_num_arguments); |
933 if (function.IsClosureFunction()) { | 931 if (function.IsClosureFunction()) { |
934 __ LeaveDartFrame(); // The arguments are still on the stack. | 932 __ LeaveDartFrame(); // The arguments are still on the stack. |
935 __ jmp(&isolate()->stub_code()->CallClosureNoSuchMethodLabel()); | 933 __ jmp(&StubCode::CallClosureNoSuchMethodLabel()); |
936 // The noSuchMethod call may return to the caller, but not here. | 934 // The noSuchMethod call may return to the caller, but not here. |
937 } else if (check_correct_named_args) { | 935 } else if (check_correct_named_args) { |
938 __ Stop("Wrong arguments"); | 936 __ Stop("Wrong arguments"); |
939 } | 937 } |
940 | 938 |
941 __ Bind(&all_arguments_processed); | 939 __ Bind(&all_arguments_processed); |
942 // Nullify originally passed arguments only after they have been copied and | 940 // Nullify originally passed arguments only after they have been copied and |
943 // checked, otherwise noSuchMethod would not see their original values. | 941 // checked, otherwise noSuchMethod would not see their original values. |
944 // This step can be skipped in case we decide that formal parameters are | 942 // This step can be skipped in case we decide that formal parameters are |
945 // implicitly final, since garbage collecting the unmodified value is not | 943 // implicitly final, since garbage collecting the unmodified value is not |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1026 // Reoptimization of an optimized function is triggered by counting in | 1024 // Reoptimization of an optimized function is triggered by counting in |
1027 // IC stubs, but not at the entry of the function. | 1025 // IC stubs, but not at the entry of the function. |
1028 if (!is_optimizing()) { | 1026 if (!is_optimizing()) { |
1029 __ incl(FieldAddress(function_reg, Function::usage_counter_offset())); | 1027 __ incl(FieldAddress(function_reg, Function::usage_counter_offset())); |
1030 } | 1028 } |
1031 __ cmpl( | 1029 __ cmpl( |
1032 FieldAddress(function_reg, Function::usage_counter_offset()), | 1030 FieldAddress(function_reg, Function::usage_counter_offset()), |
1033 Immediate(GetOptimizationThreshold())); | 1031 Immediate(GetOptimizationThreshold())); |
1034 ASSERT(function_reg == RDI); | 1032 ASSERT(function_reg == RDI); |
1035 __ J(GREATER_EQUAL, | 1033 __ J(GREATER_EQUAL, |
1036 &isolate()->stub_code()->OptimizeFunctionLabel(), | 1034 &StubCode::OptimizeFunctionLabel(), |
1037 new_pp); | 1035 new_pp); |
1038 } else { | 1036 } else { |
1039 entry_patch_pc_offset_ = assembler()->CodeSize(); | 1037 entry_patch_pc_offset_ = assembler()->CodeSize(); |
1040 } | 1038 } |
1041 ASSERT(StackSize() >= 0); | 1039 ASSERT(StackSize() >= 0); |
1042 __ Comment("Enter frame"); | 1040 __ Comment("Enter frame"); |
1043 __ EnterDartFrameWithInfo(StackSize() * kWordSize, new_pp, new_pc); | 1041 __ EnterDartFrameWithInfo(StackSize() * kWordSize, new_pp, new_pc); |
1044 } | 1042 } |
1045 } | 1043 } |
1046 | 1044 |
1047 | 1045 |
1048 void FlowGraphCompiler::CompileGraph() { | 1046 void FlowGraphCompiler::CompileGraph() { |
1049 InitCompiler(); | 1047 InitCompiler(); |
1050 | 1048 |
1051 TryIntrinsify(); | 1049 TryIntrinsify(); |
1052 | 1050 |
1053 EmitFrameEntry(); | 1051 EmitFrameEntry(); |
1054 | 1052 |
1055 const Function& function = parsed_function().function(); | 1053 const Function& function = parsed_function().function(); |
1056 | 1054 |
1057 const int num_fixed_params = function.num_fixed_parameters(); | 1055 const int num_fixed_params = function.num_fixed_parameters(); |
1058 const int num_copied_params = parsed_function().num_copied_params(); | 1056 const int num_copied_params = parsed_function().num_copied_params(); |
1059 const int num_locals = parsed_function().num_stack_locals(); | 1057 const int num_locals = parsed_function().num_stack_locals(); |
1060 StubCode* stub_code = isolate()->stub_code(); | |
1061 | 1058 |
1062 // We check the number of passed arguments when we have to copy them due to | 1059 // We check the number of passed arguments when we have to copy them due to |
1063 // the presence of optional parameters. | 1060 // the presence of optional parameters. |
1064 // No such checking code is generated if only fixed parameters are declared, | 1061 // No such checking code is generated if only fixed parameters are declared, |
1065 // unless we are in debug mode or unless we are compiling a closure. | 1062 // unless we are in debug mode or unless we are compiling a closure. |
1066 if (num_copied_params == 0) { | 1063 if (num_copied_params == 0) { |
1067 #ifdef DEBUG | 1064 #ifdef DEBUG |
1068 ASSERT(!parsed_function().function().HasOptionalParameters()); | 1065 ASSERT(!parsed_function().function().HasOptionalParameters()); |
1069 const bool check_arguments = !flow_graph().IsCompiledForOsr(); | 1066 const bool check_arguments = !flow_graph().IsCompiledForOsr(); |
1070 #else | 1067 #else |
1071 const bool check_arguments = | 1068 const bool check_arguments = |
1072 function.IsClosureFunction() && !flow_graph().IsCompiledForOsr(); | 1069 function.IsClosureFunction() && !flow_graph().IsCompiledForOsr(); |
1073 #endif | 1070 #endif |
1074 if (check_arguments) { | 1071 if (check_arguments) { |
1075 __ Comment("Check argument count"); | 1072 __ Comment("Check argument count"); |
1076 // Check that exactly num_fixed arguments are passed in. | 1073 // Check that exactly num_fixed arguments are passed in. |
1077 Label correct_num_arguments, wrong_num_arguments; | 1074 Label correct_num_arguments, wrong_num_arguments; |
1078 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset())); | 1075 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset())); |
1079 __ CompareImmediate(RAX, Immediate(Smi::RawValue(num_fixed_params)), PP); | 1076 __ CompareImmediate(RAX, Immediate(Smi::RawValue(num_fixed_params)), PP); |
1080 __ j(NOT_EQUAL, &wrong_num_arguments, Assembler::kNearJump); | 1077 __ j(NOT_EQUAL, &wrong_num_arguments, Assembler::kNearJump); |
1081 __ cmpq(RAX, | 1078 __ cmpq(RAX, |
1082 FieldAddress(R10, | 1079 FieldAddress(R10, |
1083 ArgumentsDescriptor::positional_count_offset())); | 1080 ArgumentsDescriptor::positional_count_offset())); |
1084 __ j(EQUAL, &correct_num_arguments, Assembler::kNearJump); | 1081 __ j(EQUAL, &correct_num_arguments, Assembler::kNearJump); |
1085 | 1082 |
1086 __ Bind(&wrong_num_arguments); | 1083 __ Bind(&wrong_num_arguments); |
1087 if (function.IsClosureFunction()) { | 1084 if (function.IsClosureFunction()) { |
1088 __ LeaveDartFrame(); // The arguments are still on the stack. | 1085 __ LeaveDartFrame(); // The arguments are still on the stack. |
1089 __ jmp(&stub_code->CallClosureNoSuchMethodLabel()); | 1086 __ jmp(&StubCode::CallClosureNoSuchMethodLabel()); |
1090 // The noSuchMethod call may return to the caller, but not here. | 1087 // The noSuchMethod call may return to the caller, but not here. |
1091 } else { | 1088 } else { |
1092 __ Stop("Wrong number of arguments"); | 1089 __ Stop("Wrong number of arguments"); |
1093 } | 1090 } |
1094 __ Bind(&correct_num_arguments); | 1091 __ Bind(&correct_num_arguments); |
1095 } | 1092 } |
1096 } else if (!flow_graph().IsCompiledForOsr()) { | 1093 } else if (!flow_graph().IsCompiledForOsr()) { |
1097 CopyParameters(); | 1094 CopyParameters(); |
1098 } | 1095 } |
1099 | 1096 |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1145 ASSERT(!block_order().is_empty()); | 1142 ASSERT(!block_order().is_empty()); |
1146 VisitBlocks(); | 1143 VisitBlocks(); |
1147 | 1144 |
1148 __ int3(); | 1145 __ int3(); |
1149 GenerateDeferredCode(); | 1146 GenerateDeferredCode(); |
1150 // Emit function patching code. This will be swapped with the first 13 bytes | 1147 // Emit function patching code. This will be swapped with the first 13 bytes |
1151 // at entry point. | 1148 // at entry point. |
1152 patch_code_pc_offset_ = assembler()->CodeSize(); | 1149 patch_code_pc_offset_ = assembler()->CodeSize(); |
1153 // This is patched up to a point in FrameEntry where the PP for the | 1150 // This is patched up to a point in FrameEntry where the PP for the |
1154 // current function is in R13 instead of PP. | 1151 // current function is in R13 instead of PP. |
1155 __ JmpPatchable(&stub_code->FixCallersTargetLabel(), R13); | 1152 __ JmpPatchable(&StubCode::FixCallersTargetLabel(), R13); |
1156 | 1153 |
1157 if (is_optimizing()) { | 1154 if (is_optimizing()) { |
1158 lazy_deopt_pc_offset_ = assembler()->CodeSize(); | 1155 lazy_deopt_pc_offset_ = assembler()->CodeSize(); |
1159 __ Jmp(&stub_code->DeoptimizeLazyLabel(), PP); | 1156 __ Jmp(&StubCode::DeoptimizeLazyLabel(), PP); |
1160 } | 1157 } |
1161 } | 1158 } |
1162 | 1159 |
1163 | 1160 |
1164 void FlowGraphCompiler::GenerateCall(intptr_t token_pos, | 1161 void FlowGraphCompiler::GenerateCall(intptr_t token_pos, |
1165 const ExternalLabel* label, | 1162 const ExternalLabel* label, |
1166 RawPcDescriptors::Kind kind, | 1163 RawPcDescriptors::Kind kind, |
1167 LocationSummary* locs) { | 1164 LocationSummary* locs) { |
1168 __ Call(label, PP); | 1165 __ Call(label, PP); |
1169 AddCurrentDescriptor(kind, Isolate::kNoDeoptId, token_pos); | 1166 AddCurrentDescriptor(kind, Isolate::kNoDeoptId, token_pos); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1214 } | 1211 } |
1215 } | 1212 } |
1216 | 1213 |
1217 | 1214 |
1218 void FlowGraphCompiler::EmitUnoptimizedStaticCall( | 1215 void FlowGraphCompiler::EmitUnoptimizedStaticCall( |
1219 intptr_t argument_count, | 1216 intptr_t argument_count, |
1220 intptr_t deopt_id, | 1217 intptr_t deopt_id, |
1221 intptr_t token_pos, | 1218 intptr_t token_pos, |
1222 LocationSummary* locs, | 1219 LocationSummary* locs, |
1223 const ICData& ic_data) { | 1220 const ICData& ic_data) { |
1224 StubCode* stub_code = isolate()->stub_code(); | |
1225 const uword label_address = | 1221 const uword label_address = |
1226 stub_code->UnoptimizedStaticCallEntryPoint(ic_data.NumArgsTested()); | 1222 StubCode::UnoptimizedStaticCallEntryPoint(ic_data.NumArgsTested()); |
1227 ExternalLabel target_label(label_address); | 1223 ExternalLabel target_label(label_address); |
1228 __ LoadObject(RBX, ic_data, PP); | 1224 __ LoadObject(RBX, ic_data, PP); |
1229 GenerateDartCall(deopt_id, | 1225 GenerateDartCall(deopt_id, |
1230 token_pos, | 1226 token_pos, |
1231 &target_label, | 1227 &target_label, |
1232 RawPcDescriptors::kUnoptStaticCall, | 1228 RawPcDescriptors::kUnoptStaticCall, |
1233 locs); | 1229 locs); |
1234 __ Drop(argument_count, RCX); | 1230 __ Drop(argument_count, RCX); |
1235 } | 1231 } |
1236 | 1232 |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1318 ASSERT(!arguments_descriptor.IsNull() && (arguments_descriptor.Length() > 0)); | 1314 ASSERT(!arguments_descriptor.IsNull() && (arguments_descriptor.Length() > 0)); |
1319 const MegamorphicCache& cache = | 1315 const MegamorphicCache& cache = |
1320 MegamorphicCache::ZoneHandle(table->Lookup(name, arguments_descriptor)); | 1316 MegamorphicCache::ZoneHandle(table->Lookup(name, arguments_descriptor)); |
1321 const Register receiverR = RDI; | 1317 const Register receiverR = RDI; |
1322 const Register cacheR = RBX; | 1318 const Register cacheR = RBX; |
1323 const Register targetR = RCX; | 1319 const Register targetR = RCX; |
1324 __ movq(receiverR, Address(RSP, (argument_count - 1) * kWordSize)); | 1320 __ movq(receiverR, Address(RSP, (argument_count - 1) * kWordSize)); |
1325 __ LoadObject(cacheR, cache, PP); | 1321 __ LoadObject(cacheR, cache, PP); |
1326 | 1322 |
1327 if (FLAG_use_megamorphic_stub) { | 1323 if (FLAG_use_megamorphic_stub) { |
1328 StubCode* stub_code = isolate()->stub_code(); | 1324 __ call(&StubCode::MegamorphicLookupLabel()); |
1329 __ call(&stub_code->MegamorphicLookupLabel()); | |
1330 } else { | 1325 } else { |
1331 StubCode::EmitMegamorphicLookup(assembler(), receiverR, cacheR, targetR); | 1326 StubCode::EmitMegamorphicLookup(assembler(), receiverR, cacheR, targetR); |
1332 } | 1327 } |
1333 __ LoadObject(RBX, ic_data, PP); | 1328 __ LoadObject(RBX, ic_data, PP); |
1334 __ LoadObject(R10, arguments_descriptor, PP); | 1329 __ LoadObject(R10, arguments_descriptor, PP); |
1335 __ call(targetR); | 1330 __ call(targetR); |
1336 AddCurrentDescriptor(RawPcDescriptors::kOther, | 1331 AddCurrentDescriptor(RawPcDescriptors::kOther, |
1337 Isolate::kNoDeoptId, token_pos); | 1332 Isolate::kNoDeoptId, token_pos); |
1338 RecordSafepoint(locs); | 1333 RecordSafepoint(locs); |
1339 const intptr_t deopt_id_after = Isolate::ToDeoptAfter(deopt_id); | 1334 const intptr_t deopt_id_after = Isolate::ToDeoptAfter(deopt_id); |
1340 if (is_optimizing()) { | 1335 if (is_optimizing()) { |
1341 AddDeoptIndexAtCall(deopt_id_after, token_pos); | 1336 AddDeoptIndexAtCall(deopt_id_after, token_pos); |
1342 } else { | 1337 } else { |
1343 // Add deoptimization continuation point after the call and before the | 1338 // Add deoptimization continuation point after the call and before the |
1344 // arguments are removed. | 1339 // arguments are removed. |
1345 AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id_after, token_pos); | 1340 AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id_after, token_pos); |
1346 } | 1341 } |
1347 __ Drop(argument_count, RCX); | 1342 __ Drop(argument_count, RCX); |
1348 } | 1343 } |
1349 | 1344 |
1350 | 1345 |
1351 void FlowGraphCompiler::EmitOptimizedStaticCall( | 1346 void FlowGraphCompiler::EmitOptimizedStaticCall( |
1352 const Function& function, | 1347 const Function& function, |
1353 const Array& arguments_descriptor, | 1348 const Array& arguments_descriptor, |
1354 intptr_t argument_count, | 1349 intptr_t argument_count, |
1355 intptr_t deopt_id, | 1350 intptr_t deopt_id, |
1356 intptr_t token_pos, | 1351 intptr_t token_pos, |
1357 LocationSummary* locs) { | 1352 LocationSummary* locs) { |
1358 StubCode* stub_code = isolate()->stub_code(); | |
1359 __ LoadObject(R10, arguments_descriptor, PP); | 1353 __ LoadObject(R10, arguments_descriptor, PP); |
1360 // Do not use the code from the function, but let the code be patched so that | 1354 // Do not use the code from the function, but let the code be patched so that |
1361 // we can record the outgoing edges to other code. | 1355 // we can record the outgoing edges to other code. |
1362 GenerateDartCall(deopt_id, | 1356 GenerateDartCall(deopt_id, |
1363 token_pos, | 1357 token_pos, |
1364 &stub_code->CallStaticFunctionLabel(), | 1358 &StubCode::CallStaticFunctionLabel(), |
1365 RawPcDescriptors::kOther, | 1359 RawPcDescriptors::kOther, |
1366 locs); | 1360 locs); |
1367 AddStaticCallTarget(function); | 1361 AddStaticCallTarget(function); |
1368 __ Drop(argument_count, RCX); | 1362 __ Drop(argument_count, RCX); |
1369 } | 1363 } |
1370 | 1364 |
1371 | 1365 |
1372 Condition FlowGraphCompiler::EmitEqualityRegConstCompare( | 1366 Condition FlowGraphCompiler::EmitEqualityRegConstCompare( |
1373 Register reg, | 1367 Register reg, |
1374 const Object& obj, | 1368 const Object& obj, |
1375 bool needs_number_check, | 1369 bool needs_number_check, |
1376 intptr_t token_pos) { | 1370 intptr_t token_pos) { |
1377 ASSERT(!needs_number_check || | 1371 ASSERT(!needs_number_check || |
1378 (!obj.IsMint() && !obj.IsDouble() && !obj.IsBigint())); | 1372 (!obj.IsMint() && !obj.IsDouble() && !obj.IsBigint())); |
1379 | 1373 |
1380 if (obj.IsSmi() && (Smi::Cast(obj).Value() == 0)) { | 1374 if (obj.IsSmi() && (Smi::Cast(obj).Value() == 0)) { |
1381 ASSERT(!needs_number_check); | 1375 ASSERT(!needs_number_check); |
1382 __ testq(reg, reg); | 1376 __ testq(reg, reg); |
1383 return EQUAL; | 1377 return EQUAL; |
1384 } | 1378 } |
1385 | 1379 |
1386 if (needs_number_check) { | 1380 if (needs_number_check) { |
1387 StubCode* stub_code = isolate()->stub_code(); | |
1388 __ pushq(reg); | 1381 __ pushq(reg); |
1389 __ PushObject(obj, PP); | 1382 __ PushObject(obj, PP); |
1390 if (is_optimizing()) { | 1383 if (is_optimizing()) { |
1391 __ CallPatchable(&stub_code->OptimizedIdenticalWithNumberCheckLabel()); | 1384 __ CallPatchable(&StubCode::OptimizedIdenticalWithNumberCheckLabel()); |
1392 } else { | 1385 } else { |
1393 __ CallPatchable(&stub_code->UnoptimizedIdenticalWithNumberCheckLabel()); | 1386 __ CallPatchable(&StubCode::UnoptimizedIdenticalWithNumberCheckLabel()); |
1394 } | 1387 } |
1395 if (token_pos != Scanner::kNoSourcePos) { | 1388 if (token_pos != Scanner::kNoSourcePos) { |
1396 AddCurrentDescriptor(RawPcDescriptors::kRuntimeCall, | 1389 AddCurrentDescriptor(RawPcDescriptors::kRuntimeCall, |
1397 Isolate::kNoDeoptId, | 1390 Isolate::kNoDeoptId, |
1398 token_pos); | 1391 token_pos); |
1399 } | 1392 } |
1400 // Stub returns result in flags (result of a cmpq, we need ZF computed). | 1393 // Stub returns result in flags (result of a cmpq, we need ZF computed). |
1401 __ popq(reg); // Discard constant. | 1394 __ popq(reg); // Discard constant. |
1402 __ popq(reg); // Restore 'reg'. | 1395 __ popq(reg); // Restore 'reg'. |
1403 } else { | 1396 } else { |
1404 __ CompareObject(reg, obj, PP); | 1397 __ CompareObject(reg, obj, PP); |
1405 } | 1398 } |
1406 return EQUAL; | 1399 return EQUAL; |
1407 } | 1400 } |
1408 | 1401 |
1409 | 1402 |
1410 Condition FlowGraphCompiler::EmitEqualityRegRegCompare(Register left, | 1403 Condition FlowGraphCompiler::EmitEqualityRegRegCompare(Register left, |
1411 Register right, | 1404 Register right, |
1412 bool needs_number_check, | 1405 bool needs_number_check, |
1413 intptr_t token_pos) { | 1406 intptr_t token_pos) { |
1414 if (needs_number_check) { | 1407 if (needs_number_check) { |
1415 StubCode* stub_code = isolate()->stub_code(); | |
1416 __ pushq(left); | 1408 __ pushq(left); |
1417 __ pushq(right); | 1409 __ pushq(right); |
1418 if (is_optimizing()) { | 1410 if (is_optimizing()) { |
1419 __ CallPatchable(&stub_code->OptimizedIdenticalWithNumberCheckLabel()); | 1411 __ CallPatchable(&StubCode::OptimizedIdenticalWithNumberCheckLabel()); |
1420 } else { | 1412 } else { |
1421 __ CallPatchable(&stub_code->UnoptimizedIdenticalWithNumberCheckLabel()); | 1413 __ CallPatchable(&StubCode::UnoptimizedIdenticalWithNumberCheckLabel()); |
1422 } | 1414 } |
1423 if (token_pos != Scanner::kNoSourcePos) { | 1415 if (token_pos != Scanner::kNoSourcePos) { |
1424 AddCurrentDescriptor(RawPcDescriptors::kRuntimeCall, | 1416 AddCurrentDescriptor(RawPcDescriptors::kRuntimeCall, |
1425 Isolate::kNoDeoptId, | 1417 Isolate::kNoDeoptId, |
1426 token_pos); | 1418 token_pos); |
1427 } | 1419 } |
1428 // Stub returns result in flags (result of a cmpq, we need ZF computed). | 1420 // Stub returns result in flags (result of a cmpq, we need ZF computed). |
1429 __ popq(right); | 1421 __ popq(right); |
1430 __ popq(left); | 1422 __ popq(left); |
1431 } else { | 1423 } else { |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1477 Label* match_found, | 1469 Label* match_found, |
1478 intptr_t deopt_id, | 1470 intptr_t deopt_id, |
1479 intptr_t token_index, | 1471 intptr_t token_index, |
1480 LocationSummary* locs) { | 1472 LocationSummary* locs) { |
1481 ASSERT(is_optimizing()); | 1473 ASSERT(is_optimizing()); |
1482 | 1474 |
1483 __ Comment("EmitTestAndCall"); | 1475 __ Comment("EmitTestAndCall"); |
1484 const Array& arguments_descriptor = | 1476 const Array& arguments_descriptor = |
1485 Array::ZoneHandle(ArgumentsDescriptor::New(argument_count, | 1477 Array::ZoneHandle(ArgumentsDescriptor::New(argument_count, |
1486 argument_names)); | 1478 argument_names)); |
1487 StubCode* stub_code = isolate()->stub_code(); | |
1488 // Load receiver into RAX. | 1479 // Load receiver into RAX. |
1489 __ movq(RAX, | 1480 __ movq(RAX, |
1490 Address(RSP, (argument_count - 1) * kWordSize)); | 1481 Address(RSP, (argument_count - 1) * kWordSize)); |
1491 __ LoadObject(R10, arguments_descriptor, PP); | 1482 __ LoadObject(R10, arguments_descriptor, PP); |
1492 | 1483 |
1493 const bool kFirstCheckIsSmi = ic_data.GetReceiverClassIdAt(0) == kSmiCid; | 1484 const bool kFirstCheckIsSmi = ic_data.GetReceiverClassIdAt(0) == kSmiCid; |
1494 const intptr_t kNumChecks = ic_data.NumberOfChecks(); | 1485 const intptr_t kNumChecks = ic_data.NumberOfChecks(); |
1495 | 1486 |
1496 ASSERT(!ic_data.IsNull() && (kNumChecks > 0)); | 1487 ASSERT(!ic_data.IsNull() && (kNumChecks > 0)); |
1497 | 1488 |
1498 Label after_smi_test; | 1489 Label after_smi_test; |
1499 __ testq(RAX, Immediate(kSmiTagMask)); | 1490 __ testq(RAX, Immediate(kSmiTagMask)); |
1500 if (kFirstCheckIsSmi) { | 1491 if (kFirstCheckIsSmi) { |
1501 // Jump if receiver is not Smi. | 1492 // Jump if receiver is not Smi. |
1502 if (kNumChecks == 1) { | 1493 if (kNumChecks == 1) { |
1503 __ j(NOT_ZERO, failed); | 1494 __ j(NOT_ZERO, failed); |
1504 } else { | 1495 } else { |
1505 __ j(NOT_ZERO, &after_smi_test); | 1496 __ j(NOT_ZERO, &after_smi_test); |
1506 } | 1497 } |
1507 // Do not use the code from the function, but let the code be patched so | 1498 // Do not use the code from the function, but let the code be patched so |
1508 // that we can record the outgoing edges to other code. | 1499 // that we can record the outgoing edges to other code. |
1509 GenerateDartCall(deopt_id, | 1500 GenerateDartCall(deopt_id, |
1510 token_index, | 1501 token_index, |
1511 &stub_code->CallStaticFunctionLabel(), | 1502 &StubCode::CallStaticFunctionLabel(), |
1512 RawPcDescriptors::kOther, | 1503 RawPcDescriptors::kOther, |
1513 locs); | 1504 locs); |
1514 const Function& function = Function::Handle(ic_data.GetTargetAt(0)); | 1505 const Function& function = Function::Handle(ic_data.GetTargetAt(0)); |
1515 AddStaticCallTarget(function); | 1506 AddStaticCallTarget(function); |
1516 __ Drop(argument_count, RCX); | 1507 __ Drop(argument_count, RCX); |
1517 if (kNumChecks > 1) { | 1508 if (kNumChecks > 1) { |
1518 __ jmp(match_found); | 1509 __ jmp(match_found); |
1519 } | 1510 } |
1520 } else { | 1511 } else { |
1521 // Receiver is Smi, but Smi is not a valid class therefore fail. | 1512 // Receiver is Smi, but Smi is not a valid class therefore fail. |
(...skipping 20 matching lines...) Expand all Loading... |
1542 __ cmpl(RDI, Immediate(sorted[i].cid)); | 1533 __ cmpl(RDI, Immediate(sorted[i].cid)); |
1543 if (kIsLastCheck) { | 1534 if (kIsLastCheck) { |
1544 __ j(NOT_EQUAL, failed); | 1535 __ j(NOT_EQUAL, failed); |
1545 } else { | 1536 } else { |
1546 __ j(NOT_EQUAL, &next_test); | 1537 __ j(NOT_EQUAL, &next_test); |
1547 } | 1538 } |
1548 // Do not use the code from the function, but let the code be patched so | 1539 // Do not use the code from the function, but let the code be patched so |
1549 // that we can record the outgoing edges to other code. | 1540 // that we can record the outgoing edges to other code. |
1550 GenerateDartCall(deopt_id, | 1541 GenerateDartCall(deopt_id, |
1551 token_index, | 1542 token_index, |
1552 &stub_code->CallStaticFunctionLabel(), | 1543 &StubCode::CallStaticFunctionLabel(), |
1553 RawPcDescriptors::kOther, | 1544 RawPcDescriptors::kOther, |
1554 locs); | 1545 locs); |
1555 const Function& function = *sorted[i].target; | 1546 const Function& function = *sorted[i].target; |
1556 AddStaticCallTarget(function); | 1547 AddStaticCallTarget(function); |
1557 __ Drop(argument_count, RCX); | 1548 __ Drop(argument_count, RCX); |
1558 if (!kIsLastCheck) { | 1549 if (!kIsLastCheck) { |
1559 __ jmp(match_found); | 1550 __ jmp(match_found); |
1560 } | 1551 } |
1561 __ Bind(&next_test); | 1552 __ Bind(&next_test); |
1562 } | 1553 } |
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1794 __ movups(reg, Address(RSP, 0)); | 1785 __ movups(reg, Address(RSP, 0)); |
1795 __ AddImmediate(RSP, Immediate(kFpuRegisterSize), PP); | 1786 __ AddImmediate(RSP, Immediate(kFpuRegisterSize), PP); |
1796 } | 1787 } |
1797 | 1788 |
1798 | 1789 |
1799 #undef __ | 1790 #undef __ |
1800 | 1791 |
1801 } // namespace dart | 1792 } // namespace dart |
1802 | 1793 |
1803 #endif // defined TARGET_ARCH_X64 | 1794 #endif // defined TARGET_ARCH_X64 |
OLD | NEW |