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_IA32. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. |
6 #if defined(TARGET_ARCH_IA32) | 6 #if defined(TARGET_ARCH_IA32) |
7 | 7 |
8 #include "vm/flow_graph_compiler.h" | 8 #include "vm/flow_graph_compiler.h" |
9 | 9 |
10 #include "vm/ast_printer.h" | 10 #include "vm/ast_printer.h" |
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
186 Assembler* assem = compiler->assembler(); | 186 Assembler* assem = compiler->assembler(); |
187 #define __ assem-> | 187 #define __ assem-> |
188 __ Comment("%s", Name()); | 188 __ Comment("%s", Name()); |
189 __ Bind(entry_label()); | 189 __ Bind(entry_label()); |
190 if (FLAG_trap_on_deoptimization) { | 190 if (FLAG_trap_on_deoptimization) { |
191 __ int3(); | 191 __ int3(); |
192 } | 192 } |
193 | 193 |
194 ASSERT(deopt_env() != NULL); | 194 ASSERT(deopt_env() != NULL); |
195 | 195 |
196 __ call(&StubCode::DeoptimizeLabel()); | 196 __ Call(*StubCode::Deoptimize_entry()); |
197 set_pc_offset(assem->CodeSize()); | 197 set_pc_offset(assem->CodeSize()); |
198 __ int3(); | 198 __ int3(); |
199 #undef __ | 199 #undef __ |
200 } | 200 } |
201 | 201 |
202 | 202 |
203 #define __ assembler()-> | 203 #define __ assembler()-> |
204 | 204 |
205 | 205 |
206 // Fall through if bool_register contains null. | 206 // Fall through if bool_register contains null. |
(...skipping 23 matching lines...) Expand all Loading... |
230 const SubtypeTestCache& type_test_cache = | 230 const SubtypeTestCache& type_test_cache = |
231 SubtypeTestCache::ZoneHandle(zone(), SubtypeTestCache::New()); | 231 SubtypeTestCache::ZoneHandle(zone(), SubtypeTestCache::New()); |
232 const Immediate& raw_null = | 232 const Immediate& raw_null = |
233 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 233 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
234 __ LoadObject(temp_reg, type_test_cache); | 234 __ LoadObject(temp_reg, type_test_cache); |
235 __ pushl(temp_reg); // Subtype test cache. | 235 __ pushl(temp_reg); // Subtype test cache. |
236 __ pushl(instance_reg); // Instance. | 236 __ pushl(instance_reg); // Instance. |
237 if (test_kind == kTestTypeOneArg) { | 237 if (test_kind == kTestTypeOneArg) { |
238 ASSERT(type_arguments_reg == kNoRegister); | 238 ASSERT(type_arguments_reg == kNoRegister); |
239 __ pushl(raw_null); | 239 __ pushl(raw_null); |
240 __ call(&StubCode::Subtype1TestCacheLabel()); | 240 __ Call(*StubCode::Subtype1TestCache_entry()); |
241 } else if (test_kind == kTestTypeTwoArgs) { | 241 } else if (test_kind == kTestTypeTwoArgs) { |
242 ASSERT(type_arguments_reg == kNoRegister); | 242 ASSERT(type_arguments_reg == kNoRegister); |
243 __ pushl(raw_null); | 243 __ pushl(raw_null); |
244 __ call(&StubCode::Subtype2TestCacheLabel()); | 244 __ Call(*StubCode::Subtype2TestCache_entry()); |
245 } else if (test_kind == kTestTypeThreeArgs) { | 245 } else if (test_kind == kTestTypeThreeArgs) { |
246 __ pushl(type_arguments_reg); | 246 __ pushl(type_arguments_reg); |
247 __ call(&StubCode::Subtype3TestCacheLabel()); | 247 __ Call(*StubCode::Subtype3TestCache_entry()); |
248 } else { | 248 } else { |
249 UNREACHABLE(); | 249 UNREACHABLE(); |
250 } | 250 } |
251 // Result is in ECX: null -> not found, otherwise Bool::True or Bool::False. | 251 // Result is in ECX: null -> not found, otherwise Bool::True or Bool::False. |
252 ASSERT(instance_reg != ECX); | 252 ASSERT(instance_reg != ECX); |
253 ASSERT(temp_reg != ECX); | 253 ASSERT(temp_reg != ECX); |
254 __ popl(instance_reg); // Discard. | 254 __ popl(instance_reg); // Discard. |
255 __ popl(instance_reg); // Restore receiver. | 255 __ popl(instance_reg); // Restore receiver. |
256 __ popl(temp_reg); // Discard. | 256 __ popl(temp_reg); // Discard. |
257 GenerateBoolToJump(ECX, is_instance_lbl, is_not_instance_lbl); | 257 GenerateBoolToJump(ECX, is_instance_lbl, is_not_instance_lbl); |
(...skipping 678 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
936 __ SmiUntag(EBX); | 936 __ SmiUntag(EBX); |
937 // Check that ECX equals EBX, i.e. no named arguments passed. | 937 // Check that ECX equals EBX, i.e. no named arguments passed. |
938 __ cmpl(ECX, EBX); | 938 __ cmpl(ECX, EBX); |
939 __ j(EQUAL, &all_arguments_processed, Assembler::kNearJump); | 939 __ j(EQUAL, &all_arguments_processed, Assembler::kNearJump); |
940 } | 940 } |
941 } | 941 } |
942 | 942 |
943 __ Bind(&wrong_num_arguments); | 943 __ Bind(&wrong_num_arguments); |
944 if (function.IsClosureFunction()) { | 944 if (function.IsClosureFunction()) { |
945 __ LeaveFrame(); // The arguments are still on the stack. | 945 __ LeaveFrame(); // The arguments are still on the stack. |
946 __ jmp(&StubCode::CallClosureNoSuchMethodLabel()); | 946 __ Jmp(*StubCode::CallClosureNoSuchMethod_entry()); |
947 // The noSuchMethod call may return to the caller, but not here. | 947 // The noSuchMethod call may return to the caller, but not here. |
948 } else if (check_correct_named_args) { | 948 } else if (check_correct_named_args) { |
949 __ Stop("Wrong arguments"); | 949 __ Stop("Wrong arguments"); |
950 } | 950 } |
951 | 951 |
952 __ Bind(&all_arguments_processed); | 952 __ Bind(&all_arguments_processed); |
953 // Nullify originally passed arguments only after they have been copied and | 953 // Nullify originally passed arguments only after they have been copied and |
954 // checked, otherwise noSuchMethod would not see their original values. | 954 // checked, otherwise noSuchMethod would not see their original values. |
955 // This step can be skipped in case we decide that formal parameters are | 955 // This step can be skipped in case we decide that formal parameters are |
956 // implicitly final, since garbage collecting the unmodified value is not | 956 // implicitly final, since garbage collecting the unmodified value is not |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1012 entry_patch_pc_offset_ = assembler()->CodeSize(); | 1012 entry_patch_pc_offset_ = assembler()->CodeSize(); |
1013 | 1013 |
1014 // Reoptimization of an optimized function is triggered by counting in | 1014 // Reoptimization of an optimized function is triggered by counting in |
1015 // IC stubs, but not at the entry of the function. | 1015 // IC stubs, but not at the entry of the function. |
1016 if (!is_optimizing()) { | 1016 if (!is_optimizing()) { |
1017 __ incl(FieldAddress(function_reg, Function::usage_counter_offset())); | 1017 __ incl(FieldAddress(function_reg, Function::usage_counter_offset())); |
1018 } | 1018 } |
1019 __ cmpl(FieldAddress(function_reg, Function::usage_counter_offset()), | 1019 __ cmpl(FieldAddress(function_reg, Function::usage_counter_offset()), |
1020 Immediate(GetOptimizationThreshold())); | 1020 Immediate(GetOptimizationThreshold())); |
1021 ASSERT(function_reg == EDI); | 1021 ASSERT(function_reg == EDI); |
1022 __ j(GREATER_EQUAL, &StubCode::OptimizeFunctionLabel()); | 1022 __ J(GREATER_EQUAL, *StubCode::OptimizeFunction_entry()); |
1023 } else if (!flow_graph().IsCompiledForOsr()) { | 1023 } else if (!flow_graph().IsCompiledForOsr()) { |
1024 entry_patch_pc_offset_ = assembler()->CodeSize(); | 1024 entry_patch_pc_offset_ = assembler()->CodeSize(); |
1025 } | 1025 } |
1026 __ Comment("Enter frame"); | 1026 __ Comment("Enter frame"); |
1027 if (flow_graph().IsCompiledForOsr()) { | 1027 if (flow_graph().IsCompiledForOsr()) { |
1028 intptr_t extra_slots = StackSize() | 1028 intptr_t extra_slots = StackSize() |
1029 - flow_graph().num_stack_locals() | 1029 - flow_graph().num_stack_locals() |
1030 - flow_graph().num_copied_params(); | 1030 - flow_graph().num_copied_params(); |
1031 ASSERT(extra_slots >= 0); | 1031 ASSERT(extra_slots >= 0); |
1032 __ EnterOsrFrame(extra_slots * kWordSize); | 1032 __ EnterOsrFrame(extra_slots * kWordSize); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1070 __ cmpl(EAX, Immediate(Smi::RawValue(num_fixed_params))); | 1070 __ cmpl(EAX, Immediate(Smi::RawValue(num_fixed_params))); |
1071 __ j(NOT_EQUAL, &wrong_num_arguments, Assembler::kNearJump); | 1071 __ j(NOT_EQUAL, &wrong_num_arguments, Assembler::kNearJump); |
1072 __ cmpl(EAX, | 1072 __ cmpl(EAX, |
1073 FieldAddress(EDX, | 1073 FieldAddress(EDX, |
1074 ArgumentsDescriptor::positional_count_offset())); | 1074 ArgumentsDescriptor::positional_count_offset())); |
1075 __ j(EQUAL, &correct_num_arguments, Assembler::kNearJump); | 1075 __ j(EQUAL, &correct_num_arguments, Assembler::kNearJump); |
1076 | 1076 |
1077 __ Bind(&wrong_num_arguments); | 1077 __ Bind(&wrong_num_arguments); |
1078 if (function.IsClosureFunction()) { | 1078 if (function.IsClosureFunction()) { |
1079 __ LeaveFrame(); // The arguments are still on the stack. | 1079 __ LeaveFrame(); // The arguments are still on the stack. |
1080 __ jmp(&StubCode::CallClosureNoSuchMethodLabel()); | 1080 __ Jmp(*StubCode::CallClosureNoSuchMethod_entry()); |
1081 // The noSuchMethod call may return to the caller, but not here. | 1081 // The noSuchMethod call may return to the caller, but not here. |
1082 } else { | 1082 } else { |
1083 __ Stop("Wrong number of arguments"); | 1083 __ Stop("Wrong number of arguments"); |
1084 } | 1084 } |
1085 __ Bind(&correct_num_arguments); | 1085 __ Bind(&correct_num_arguments); |
1086 } | 1086 } |
1087 } else if (!flow_graph().IsCompiledForOsr()) { | 1087 } else if (!flow_graph().IsCompiledForOsr()) { |
1088 CopyParameters(); | 1088 CopyParameters(); |
1089 } | 1089 } |
1090 | 1090 |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1138 } | 1138 } |
1139 | 1139 |
1140 ASSERT(!block_order().is_empty()); | 1140 ASSERT(!block_order().is_empty()); |
1141 VisitBlocks(); | 1141 VisitBlocks(); |
1142 | 1142 |
1143 __ int3(); | 1143 __ int3(); |
1144 GenerateDeferredCode(); | 1144 GenerateDeferredCode(); |
1145 // Emit function patching code. This will be swapped with the first 5 bytes | 1145 // Emit function patching code. This will be swapped with the first 5 bytes |
1146 // at entry point. | 1146 // at entry point. |
1147 patch_code_pc_offset_ = assembler()->CodeSize(); | 1147 patch_code_pc_offset_ = assembler()->CodeSize(); |
1148 __ jmp(&StubCode::FixCallersTargetLabel()); | 1148 __ Jmp(*StubCode::FixCallersTarget_entry()); |
1149 | 1149 |
1150 if (is_optimizing()) { | 1150 if (is_optimizing()) { |
1151 lazy_deopt_pc_offset_ = assembler()->CodeSize(); | 1151 lazy_deopt_pc_offset_ = assembler()->CodeSize(); |
1152 __ jmp(&StubCode::DeoptimizeLazyLabel()); | 1152 __ Jmp(*StubCode::DeoptimizeLazy_entry()); |
1153 } | 1153 } |
1154 } | 1154 } |
1155 | 1155 |
1156 | 1156 |
1157 void FlowGraphCompiler::GenerateCall(intptr_t token_pos, | 1157 void FlowGraphCompiler::GenerateCall(intptr_t token_pos, |
1158 const ExternalLabel* label, | 1158 const StubEntry& stub_entry, |
1159 RawPcDescriptors::Kind kind, | 1159 RawPcDescriptors::Kind kind, |
1160 LocationSummary* locs) { | 1160 LocationSummary* locs) { |
1161 __ call(label); | 1161 __ Call(stub_entry); |
1162 AddCurrentDescriptor(kind, Isolate::kNoDeoptId, token_pos); | 1162 AddCurrentDescriptor(kind, Isolate::kNoDeoptId, token_pos); |
1163 RecordSafepoint(locs); | 1163 RecordSafepoint(locs); |
1164 } | 1164 } |
1165 | 1165 |
1166 | 1166 |
1167 void FlowGraphCompiler::GenerateDartCall(intptr_t deopt_id, | 1167 void FlowGraphCompiler::GenerateDartCall(intptr_t deopt_id, |
1168 intptr_t token_pos, | 1168 intptr_t token_pos, |
1169 const ExternalLabel* label, | 1169 const StubEntry& stub_entry, |
1170 RawPcDescriptors::Kind kind, | 1170 RawPcDescriptors::Kind kind, |
1171 LocationSummary* locs) { | 1171 LocationSummary* locs) { |
1172 __ call(label); | 1172 __ Call(stub_entry); |
1173 AddCurrentDescriptor(kind, deopt_id, token_pos); | 1173 AddCurrentDescriptor(kind, deopt_id, token_pos); |
1174 RecordSafepoint(locs); | 1174 RecordSafepoint(locs); |
1175 // Marks either the continuation point in unoptimized code or the | 1175 // Marks either the continuation point in unoptimized code or the |
1176 // deoptimization point in optimized code, after call. | 1176 // deoptimization point in optimized code, after call. |
1177 const intptr_t deopt_id_after = Isolate::ToDeoptAfter(deopt_id); | 1177 const intptr_t deopt_id_after = Isolate::ToDeoptAfter(deopt_id); |
1178 if (is_optimizing()) { | 1178 if (is_optimizing()) { |
1179 AddDeoptIndexAtCall(deopt_id_after, token_pos); | 1179 AddDeoptIndexAtCall(deopt_id_after, token_pos); |
1180 } else { | 1180 } else { |
1181 // Add deoptimization continuation point after the call and before the | 1181 // Add deoptimization continuation point after the call and before the |
1182 // arguments are removed. | 1182 // arguments are removed. |
(...skipping 24 matching lines...) Expand all Loading... |
1207 } | 1207 } |
1208 } | 1208 } |
1209 | 1209 |
1210 | 1210 |
1211 void FlowGraphCompiler::EmitUnoptimizedStaticCall( | 1211 void FlowGraphCompiler::EmitUnoptimizedStaticCall( |
1212 intptr_t argument_count, | 1212 intptr_t argument_count, |
1213 intptr_t deopt_id, | 1213 intptr_t deopt_id, |
1214 intptr_t token_pos, | 1214 intptr_t token_pos, |
1215 LocationSummary* locs, | 1215 LocationSummary* locs, |
1216 const ICData& ic_data) { | 1216 const ICData& ic_data) { |
1217 const uword label_address = | 1217 const StubEntry& stub_entry = |
1218 StubCode::UnoptimizedStaticCallEntryPoint(ic_data.NumArgsTested()); | 1218 *StubCode::UnoptimizedStaticCallEntry(ic_data.NumArgsTested()); |
1219 ExternalLabel target_label(label_address); | |
1220 __ LoadObject(ECX, ic_data); | 1219 __ LoadObject(ECX, ic_data); |
1221 GenerateDartCall(deopt_id, | 1220 GenerateDartCall(deopt_id, |
1222 token_pos, | 1221 token_pos, |
1223 &target_label, | 1222 stub_entry, |
1224 RawPcDescriptors::kUnoptStaticCall, | 1223 RawPcDescriptors::kUnoptStaticCall, |
1225 locs); | 1224 locs); |
1226 __ Drop(argument_count); | 1225 __ Drop(argument_count); |
1227 } | 1226 } |
1228 | 1227 |
1229 | 1228 |
1230 void FlowGraphCompiler::EmitEdgeCounter() { | 1229 void FlowGraphCompiler::EmitEdgeCounter() { |
1231 // We do not check for overflow when incrementing the edge counter. The | 1230 // We do not check for overflow when incrementing the edge counter. The |
1232 // function should normally be optimized long before the counter can | 1231 // function should normally be optimized long before the counter can |
1233 // overflow; and though we do not reset the counters when we optimize or | 1232 // overflow; and though we do not reset the counters when we optimize or |
(...skipping 15 matching lines...) Expand all Loading... |
1249 | 1248 |
1250 | 1249 |
1251 int32_t FlowGraphCompiler::EdgeCounterIncrementSizeInBytes() { | 1250 int32_t FlowGraphCompiler::EdgeCounterIncrementSizeInBytes() { |
1252 const int32_t size = Isolate::Current()->edge_counter_increment_size(); | 1251 const int32_t size = Isolate::Current()->edge_counter_increment_size(); |
1253 ASSERT(size != -1); | 1252 ASSERT(size != -1); |
1254 return size; | 1253 return size; |
1255 } | 1254 } |
1256 | 1255 |
1257 | 1256 |
1258 void FlowGraphCompiler::EmitOptimizedInstanceCall( | 1257 void FlowGraphCompiler::EmitOptimizedInstanceCall( |
1259 ExternalLabel* target_label, | 1258 const StubEntry& stub_entry, |
1260 const ICData& ic_data, | 1259 const ICData& ic_data, |
1261 intptr_t argument_count, | 1260 intptr_t argument_count, |
1262 intptr_t deopt_id, | 1261 intptr_t deopt_id, |
1263 intptr_t token_pos, | 1262 intptr_t token_pos, |
1264 LocationSummary* locs) { | 1263 LocationSummary* locs) { |
1265 ASSERT(Array::Handle(ic_data.arguments_descriptor()).Length() > 0); | 1264 ASSERT(Array::Handle(ic_data.arguments_descriptor()).Length() > 0); |
1266 // Each ICData propagated from unoptimized to optimized code contains the | 1265 // Each ICData propagated from unoptimized to optimized code contains the |
1267 // function that corresponds to the Dart function of that IC call. Due | 1266 // function that corresponds to the Dart function of that IC call. Due |
1268 // to inlining in optimized code, that function may not correspond to the | 1267 // to inlining in optimized code, that function may not correspond to the |
1269 // top-level function (parsed_function().function()) which could be | 1268 // top-level function (parsed_function().function()) which could be |
1270 // reoptimized and which counter needs to be incremented. | 1269 // reoptimized and which counter needs to be incremented. |
1271 // Pass the function explicitly, it is used in IC stub. | 1270 // Pass the function explicitly, it is used in IC stub. |
1272 __ LoadObject(EDI, parsed_function().function()); | 1271 __ LoadObject(EDI, parsed_function().function()); |
1273 __ LoadObject(ECX, ic_data); | 1272 __ LoadObject(ECX, ic_data); |
1274 GenerateDartCall(deopt_id, | 1273 GenerateDartCall(deopt_id, |
1275 token_pos, | 1274 token_pos, |
1276 target_label, | 1275 stub_entry, |
1277 RawPcDescriptors::kIcCall, | 1276 RawPcDescriptors::kIcCall, |
1278 locs); | 1277 locs); |
1279 __ Drop(argument_count); | 1278 __ Drop(argument_count); |
1280 } | 1279 } |
1281 | 1280 |
1282 | 1281 |
1283 void FlowGraphCompiler::EmitInstanceCall(ExternalLabel* target_label, | 1282 void FlowGraphCompiler::EmitInstanceCall(const StubEntry& stub_entry, |
1284 const ICData& ic_data, | 1283 const ICData& ic_data, |
1285 intptr_t argument_count, | 1284 intptr_t argument_count, |
1286 intptr_t deopt_id, | 1285 intptr_t deopt_id, |
1287 intptr_t token_pos, | 1286 intptr_t token_pos, |
1288 LocationSummary* locs) { | 1287 LocationSummary* locs) { |
1289 ASSERT(Array::Handle(ic_data.arguments_descriptor()).Length() > 0); | 1288 ASSERT(Array::Handle(ic_data.arguments_descriptor()).Length() > 0); |
1290 __ LoadObject(ECX, ic_data); | 1289 __ LoadObject(ECX, ic_data); |
1291 GenerateDartCall(deopt_id, | 1290 GenerateDartCall(deopt_id, |
1292 token_pos, | 1291 token_pos, |
1293 target_label, | 1292 stub_entry, |
1294 RawPcDescriptors::kIcCall, | 1293 RawPcDescriptors::kIcCall, |
1295 locs); | 1294 locs); |
1296 __ Drop(argument_count); | 1295 __ Drop(argument_count); |
1297 } | 1296 } |
1298 | 1297 |
1299 | 1298 |
1300 void FlowGraphCompiler::EmitMegamorphicInstanceCall( | 1299 void FlowGraphCompiler::EmitMegamorphicInstanceCall( |
1301 const ICData& ic_data, | 1300 const ICData& ic_data, |
1302 intptr_t argument_count, | 1301 intptr_t argument_count, |
1303 intptr_t deopt_id, | 1302 intptr_t deopt_id, |
1304 intptr_t token_pos, | 1303 intptr_t token_pos, |
1305 LocationSummary* locs) { | 1304 LocationSummary* locs) { |
1306 MegamorphicCacheTable* table = isolate()->megamorphic_cache_table(); | 1305 MegamorphicCacheTable* table = isolate()->megamorphic_cache_table(); |
1307 const String& name = String::Handle(zone(), ic_data.target_name()); | 1306 const String& name = String::Handle(zone(), ic_data.target_name()); |
1308 const Array& arguments_descriptor = | 1307 const Array& arguments_descriptor = |
1309 Array::ZoneHandle(zone(), ic_data.arguments_descriptor()); | 1308 Array::ZoneHandle(zone(), ic_data.arguments_descriptor()); |
1310 ASSERT(!arguments_descriptor.IsNull() && (arguments_descriptor.Length() > 0)); | 1309 ASSERT(!arguments_descriptor.IsNull() && (arguments_descriptor.Length() > 0)); |
1311 const MegamorphicCache& cache = MegamorphicCache::ZoneHandle(zone(), | 1310 const MegamorphicCache& cache = MegamorphicCache::ZoneHandle(zone(), |
1312 table->Lookup(name, arguments_descriptor)); | 1311 table->Lookup(name, arguments_descriptor)); |
1313 const Register receiverR = EDI; | 1312 const Register receiverR = EDI; |
1314 const Register cacheR = EBX; | 1313 const Register cacheR = EBX; |
1315 const Register targetR = EBX; | 1314 const Register targetR = EBX; |
1316 __ movl(receiverR, Address(ESP, (argument_count - 1) * kWordSize)); | 1315 __ movl(receiverR, Address(ESP, (argument_count - 1) * kWordSize)); |
1317 __ LoadObject(cacheR, cache); | 1316 __ LoadObject(cacheR, cache); |
1318 | 1317 |
1319 if (FLAG_use_megamorphic_stub) { | 1318 if (FLAG_use_megamorphic_stub) { |
1320 __ call(&StubCode::MegamorphicLookupLabel()); | 1319 __ Call(*StubCode::MegamorphicLookup_entry()); |
1321 } else { | 1320 } else { |
1322 StubCode::EmitMegamorphicLookup(assembler(), receiverR, cacheR, targetR); | 1321 StubCode::EmitMegamorphicLookup(assembler(), receiverR, cacheR, targetR); |
1323 } | 1322 } |
1324 | 1323 |
1325 __ LoadObject(ECX, ic_data); | 1324 __ LoadObject(ECX, ic_data); |
1326 __ LoadObject(EDX, arguments_descriptor); | 1325 __ LoadObject(EDX, arguments_descriptor); |
1327 __ call(targetR); | 1326 __ call(targetR); |
1328 AddCurrentDescriptor(RawPcDescriptors::kOther, | 1327 AddCurrentDescriptor(RawPcDescriptors::kOther, |
1329 Isolate::kNoDeoptId, token_pos); | 1328 Isolate::kNoDeoptId, token_pos); |
1330 RecordSafepoint(locs); | 1329 RecordSafepoint(locs); |
(...skipping 14 matching lines...) Expand all Loading... |
1345 const Array& arguments_descriptor, | 1344 const Array& arguments_descriptor, |
1346 intptr_t argument_count, | 1345 intptr_t argument_count, |
1347 intptr_t deopt_id, | 1346 intptr_t deopt_id, |
1348 intptr_t token_pos, | 1347 intptr_t token_pos, |
1349 LocationSummary* locs) { | 1348 LocationSummary* locs) { |
1350 __ LoadObject(EDX, arguments_descriptor); | 1349 __ LoadObject(EDX, arguments_descriptor); |
1351 // Do not use the code from the function, but let the code be patched so that | 1350 // Do not use the code from the function, but let the code be patched so that |
1352 // we can record the outgoing edges to other code. | 1351 // we can record the outgoing edges to other code. |
1353 GenerateDartCall(deopt_id, | 1352 GenerateDartCall(deopt_id, |
1354 token_pos, | 1353 token_pos, |
1355 &StubCode::CallStaticFunctionLabel(), | 1354 *StubCode::CallStaticFunction_entry(), |
1356 RawPcDescriptors::kOther, | 1355 RawPcDescriptors::kOther, |
1357 locs); | 1356 locs); |
1358 AddStaticCallTarget(function); | 1357 AddStaticCallTarget(function); |
1359 __ Drop(argument_count); | 1358 __ Drop(argument_count); |
1360 } | 1359 } |
1361 | 1360 |
1362 | 1361 |
1363 Condition FlowGraphCompiler::EmitEqualityRegConstCompare( | 1362 Condition FlowGraphCompiler::EmitEqualityRegConstCompare( |
1364 Register reg, | 1363 Register reg, |
1365 const Object& obj, | 1364 const Object& obj, |
1366 bool needs_number_check, | 1365 bool needs_number_check, |
1367 intptr_t token_pos) { | 1366 intptr_t token_pos) { |
1368 ASSERT(!needs_number_check || | 1367 ASSERT(!needs_number_check || |
1369 (!obj.IsMint() && !obj.IsDouble() && !obj.IsBigint())); | 1368 (!obj.IsMint() && !obj.IsDouble() && !obj.IsBigint())); |
1370 | 1369 |
1371 if (obj.IsSmi() && (Smi::Cast(obj).Value() == 0)) { | 1370 if (obj.IsSmi() && (Smi::Cast(obj).Value() == 0)) { |
1372 ASSERT(!needs_number_check); | 1371 ASSERT(!needs_number_check); |
1373 __ testl(reg, reg); | 1372 __ testl(reg, reg); |
1374 return EQUAL; | 1373 return EQUAL; |
1375 } | 1374 } |
1376 | 1375 |
1377 if (needs_number_check) { | 1376 if (needs_number_check) { |
1378 __ pushl(reg); | 1377 __ pushl(reg); |
1379 __ PushObject(obj); | 1378 __ PushObject(obj); |
1380 if (is_optimizing()) { | 1379 if (is_optimizing()) { |
1381 __ call(&StubCode::OptimizedIdenticalWithNumberCheckLabel()); | 1380 __ Call(*StubCode::OptimizedIdenticalWithNumberCheck_entry()); |
1382 } else { | 1381 } else { |
1383 __ call(&StubCode::UnoptimizedIdenticalWithNumberCheckLabel()); | 1382 __ Call(*StubCode::UnoptimizedIdenticalWithNumberCheck_entry()); |
1384 } | 1383 } |
1385 if (token_pos != Scanner::kNoSourcePos) { | 1384 if (token_pos != Scanner::kNoSourcePos) { |
1386 AddCurrentDescriptor(RawPcDescriptors::kRuntimeCall, | 1385 AddCurrentDescriptor(RawPcDescriptors::kRuntimeCall, |
1387 Isolate::kNoDeoptId, | 1386 Isolate::kNoDeoptId, |
1388 token_pos); | 1387 token_pos); |
1389 } | 1388 } |
1390 // Stub returns result in flags (result of a cmpl, we need ZF computed). | 1389 // Stub returns result in flags (result of a cmpl, we need ZF computed). |
1391 __ popl(reg); // Discard constant. | 1390 __ popl(reg); // Discard constant. |
1392 __ popl(reg); // Restore 'reg'. | 1391 __ popl(reg); // Restore 'reg'. |
1393 } else { | 1392 } else { |
1394 __ CompareObject(reg, obj); | 1393 __ CompareObject(reg, obj); |
1395 } | 1394 } |
1396 return EQUAL; | 1395 return EQUAL; |
1397 } | 1396 } |
1398 | 1397 |
1399 | 1398 |
1400 Condition FlowGraphCompiler::EmitEqualityRegRegCompare(Register left, | 1399 Condition FlowGraphCompiler::EmitEqualityRegRegCompare(Register left, |
1401 Register right, | 1400 Register right, |
1402 bool needs_number_check, | 1401 bool needs_number_check, |
1403 intptr_t token_pos) { | 1402 intptr_t token_pos) { |
1404 if (needs_number_check) { | 1403 if (needs_number_check) { |
1405 __ pushl(left); | 1404 __ pushl(left); |
1406 __ pushl(right); | 1405 __ pushl(right); |
1407 if (is_optimizing()) { | 1406 if (is_optimizing()) { |
1408 __ call(&StubCode::OptimizedIdenticalWithNumberCheckLabel()); | 1407 __ Call(*StubCode::OptimizedIdenticalWithNumberCheck_entry()); |
1409 } else { | 1408 } else { |
1410 __ call(&StubCode::UnoptimizedIdenticalWithNumberCheckLabel()); | 1409 __ Call(*StubCode::UnoptimizedIdenticalWithNumberCheck_entry()); |
1411 } | 1410 } |
1412 if (token_pos != Scanner::kNoSourcePos) { | 1411 if (token_pos != Scanner::kNoSourcePos) { |
1413 AddCurrentDescriptor(RawPcDescriptors::kRuntimeCall, | 1412 AddCurrentDescriptor(RawPcDescriptors::kRuntimeCall, |
1414 Isolate::kNoDeoptId, | 1413 Isolate::kNoDeoptId, |
1415 token_pos); | 1414 token_pos); |
1416 } | 1415 } |
1417 // Stub returns result in flags (result of a cmpl, we need ZF computed). | 1416 // Stub returns result in flags (result of a cmpl, we need ZF computed). |
1418 __ popl(right); | 1417 __ popl(right); |
1419 __ popl(left); | 1418 __ popl(left); |
1420 } else { | 1419 } else { |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1531 // Jump if receiver is not Smi. | 1530 // Jump if receiver is not Smi. |
1532 if (kNumChecks == 1) { | 1531 if (kNumChecks == 1) { |
1533 __ j(NOT_ZERO, failed); | 1532 __ j(NOT_ZERO, failed); |
1534 } else { | 1533 } else { |
1535 __ j(NOT_ZERO, &after_smi_test); | 1534 __ j(NOT_ZERO, &after_smi_test); |
1536 } | 1535 } |
1537 // Do not use the code from the function, but let the code be patched so | 1536 // Do not use the code from the function, but let the code be patched so |
1538 // that we can record the outgoing edges to other code. | 1537 // that we can record the outgoing edges to other code. |
1539 GenerateDartCall(deopt_id, | 1538 GenerateDartCall(deopt_id, |
1540 token_index, | 1539 token_index, |
1541 &StubCode::CallStaticFunctionLabel(), | 1540 *StubCode::CallStaticFunction_entry(), |
1542 RawPcDescriptors::kOther, | 1541 RawPcDescriptors::kOther, |
1543 locs); | 1542 locs); |
1544 const Function& function = Function::Handle(zone(), ic_data.GetTargetAt(0)); | 1543 const Function& function = Function::Handle(zone(), ic_data.GetTargetAt(0)); |
1545 AddStaticCallTarget(function); | 1544 AddStaticCallTarget(function); |
1546 __ Drop(argument_count); | 1545 __ Drop(argument_count); |
1547 if (kNumChecks > 1) { | 1546 if (kNumChecks > 1) { |
1548 __ jmp(match_found); | 1547 __ jmp(match_found); |
1549 } | 1548 } |
1550 } else { | 1549 } else { |
1551 // Receiver is Smi, but Smi is not a valid class therefore fail. | 1550 // Receiver is Smi, but Smi is not a valid class therefore fail. |
(...skipping 21 matching lines...) Expand all Loading... |
1573 __ cmpl(EDI, Immediate(sorted[i].cid)); | 1572 __ cmpl(EDI, Immediate(sorted[i].cid)); |
1574 if (kIsLastCheck) { | 1573 if (kIsLastCheck) { |
1575 __ j(NOT_EQUAL, failed); | 1574 __ j(NOT_EQUAL, failed); |
1576 } else { | 1575 } else { |
1577 __ j(NOT_EQUAL, &next_test); | 1576 __ j(NOT_EQUAL, &next_test); |
1578 } | 1577 } |
1579 // Do not use the code from the function, but let the code be patched so | 1578 // Do not use the code from the function, but let the code be patched so |
1580 // that we can record the outgoing edges to other code. | 1579 // that we can record the outgoing edges to other code. |
1581 GenerateDartCall(deopt_id, | 1580 GenerateDartCall(deopt_id, |
1582 token_index, | 1581 token_index, |
1583 &StubCode::CallStaticFunctionLabel(), | 1582 *StubCode::CallStaticFunction_entry(), |
1584 RawPcDescriptors::kOther, | 1583 RawPcDescriptors::kOther, |
1585 locs); | 1584 locs); |
1586 const Function& function = *sorted[i].target; | 1585 const Function& function = *sorted[i].target; |
1587 AddStaticCallTarget(function); | 1586 AddStaticCallTarget(function); |
1588 __ Drop(argument_count); | 1587 __ Drop(argument_count); |
1589 if (!kIsLastCheck) { | 1588 if (!kIsLastCheck) { |
1590 __ jmp(match_found); | 1589 __ jmp(match_found); |
1591 } | 1590 } |
1592 __ Bind(&next_test); | 1591 __ Bind(&next_test); |
1593 } | 1592 } |
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1854 __ movups(reg, Address(ESP, 0)); | 1853 __ movups(reg, Address(ESP, 0)); |
1855 __ addl(ESP, Immediate(kFpuRegisterSize)); | 1854 __ addl(ESP, Immediate(kFpuRegisterSize)); |
1856 } | 1855 } |
1857 | 1856 |
1858 | 1857 |
1859 #undef __ | 1858 #undef __ |
1860 | 1859 |
1861 } // namespace dart | 1860 } // namespace dart |
1862 | 1861 |
1863 #endif // defined TARGET_ARCH_IA32 | 1862 #endif // defined TARGET_ARCH_IA32 |
OLD | NEW |