| 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 |