| 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 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 95 | 95 |
| 96 // Emit all kMaterializeObject instructions describing objects to be | 96 // Emit all kMaterializeObject instructions describing objects to be |
| 97 // materialized on the deoptimization as a prefix to the deoptimization info. | 97 // materialized on the deoptimization as a prefix to the deoptimization info. |
| 98 EmitMaterializations(deopt_env_, builder); | 98 EmitMaterializations(deopt_env_, builder); |
| 99 | 99 |
| 100 // The real frame starts here. | 100 // The real frame starts here. |
| 101 builder->MarkFrameStart(); | 101 builder->MarkFrameStart(); |
| 102 | 102 |
| 103 Zone* zone = compiler->zone(); | 103 Zone* zone = compiler->zone(); |
| 104 | 104 |
| 105 // Callee's PC marker is not used anymore. Pass Code::null() to set to 0. | |
| 106 builder->AddPcMarker(Function::Handle(zone), slot_ix++); | 105 builder->AddPcMarker(Function::Handle(zone), slot_ix++); |
| 107 | |
| 108 // Current FP and PC. | |
| 109 builder->AddCallerFp(slot_ix++); | 106 builder->AddCallerFp(slot_ix++); |
| 110 builder->AddReturnAddress(current->function(), deopt_id(), slot_ix++); | 107 builder->AddReturnAddress(current->function(), deopt_id(), slot_ix++); |
| 111 | 108 |
| 112 // Emit all values that are needed for materialization as a part of the | 109 // Emit all values that are needed for materialization as a part of the |
| 113 // expression stack for the bottom-most frame. This guarantees that GC | 110 // expression stack for the bottom-most frame. This guarantees that GC |
| 114 // will be able to find them during materialization. | 111 // will be able to find them during materialization. |
| 115 slot_ix = builder->EmitMaterializationArguments(slot_ix); | 112 slot_ix = builder->EmitMaterializationArguments(slot_ix); |
| 116 | 113 |
| 117 // For the innermost environment, set outgoing arguments and the locals. | 114 // For the innermost environment, set outgoing arguments and the locals. |
| 118 for (intptr_t i = current->Length() - 1; | 115 for (intptr_t i = current->Length() - 1; |
| 119 i >= current->fixed_parameter_count(); | 116 i >= current->fixed_parameter_count(); |
| 120 i--) { | 117 i--) { |
| 121 builder->AddCopy(current->ValueAt(i), current->LocationAt(i), slot_ix++); | 118 builder->AddCopy(current->ValueAt(i), current->LocationAt(i), slot_ix++); |
| 122 } | 119 } |
| 123 | 120 |
| 124 // Current PC marker and caller FP. | |
| 125 builder->AddPcMarker(current->function(), slot_ix++); | 121 builder->AddPcMarker(current->function(), slot_ix++); |
| 126 builder->AddCallerFp(slot_ix++); | 122 builder->AddCallerFp(slot_ix++); |
| 127 | 123 |
| 128 Environment* previous = current; | 124 Environment* previous = current; |
| 129 current = current->outer(); | 125 current = current->outer(); |
| 130 while (current != NULL) { | 126 while (current != NULL) { |
| 131 // For any outer environment the deopt id is that of the call instruction | 127 // For any outer environment the deopt id is that of the call instruction |
| 132 // which is recorded in the outer environment. | 128 // which is recorded in the outer environment. |
| 133 builder->AddReturnAddress( | 129 builder->AddReturnAddress( |
| 134 current->function(), | 130 current->function(), |
| (...skipping 10 matching lines...) Expand all Loading... |
| 145 | 141 |
| 146 // Set the locals, note that outgoing arguments are not in the environment. | 142 // Set the locals, note that outgoing arguments are not in the environment. |
| 147 for (intptr_t i = current->Length() - 1; | 143 for (intptr_t i = current->Length() - 1; |
| 148 i >= current->fixed_parameter_count(); | 144 i >= current->fixed_parameter_count(); |
| 149 i--) { | 145 i--) { |
| 150 builder->AddCopy(current->ValueAt(i), | 146 builder->AddCopy(current->ValueAt(i), |
| 151 current->LocationAt(i), | 147 current->LocationAt(i), |
| 152 slot_ix++); | 148 slot_ix++); |
| 153 } | 149 } |
| 154 | 150 |
| 155 // PC marker and caller FP. | |
| 156 builder->AddPcMarker(current->function(), slot_ix++); | 151 builder->AddPcMarker(current->function(), slot_ix++); |
| 157 builder->AddCallerFp(slot_ix++); | 152 builder->AddCallerFp(slot_ix++); |
| 158 | 153 |
| 159 // Iterate on the outer environment. | 154 // Iterate on the outer environment. |
| 160 previous = current; | 155 previous = current; |
| 161 current = current->outer(); | 156 current = current->outer(); |
| 162 } | 157 } |
| 163 // The previous pointer is now the outermost environment. | 158 // The previous pointer is now the outermost environment. |
| 164 ASSERT(previous != NULL); | 159 ASSERT(previous != NULL); |
| 165 | 160 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 181 ASSERT(reason() != ICData::kDeoptAtCall); | 176 ASSERT(reason() != ICData::kDeoptAtCall); |
| 182 Assembler* assem = compiler->assembler(); | 177 Assembler* assem = compiler->assembler(); |
| 183 #define __ assem-> | 178 #define __ assem-> |
| 184 __ Comment("%s", Name()); | 179 __ Comment("%s", Name()); |
| 185 __ Bind(entry_label()); | 180 __ Bind(entry_label()); |
| 186 if (FLAG_trap_on_deoptimization) { | 181 if (FLAG_trap_on_deoptimization) { |
| 187 __ int3(); | 182 __ int3(); |
| 188 } | 183 } |
| 189 | 184 |
| 190 ASSERT(deopt_env() != NULL); | 185 ASSERT(deopt_env() != NULL); |
| 191 | 186 __ pushl(CODE_REG); |
| 192 __ Call(*StubCode::Deoptimize_entry()); | 187 __ Call(*StubCode::Deoptimize_entry()); |
| 193 set_pc_offset(assem->CodeSize()); | 188 set_pc_offset(assem->CodeSize()); |
| 194 __ int3(); | 189 __ int3(); |
| 195 #undef __ | 190 #undef __ |
| 196 } | 191 } |
| 197 | 192 |
| 198 | 193 |
| 199 #define __ assembler()-> | 194 #define __ assembler()-> |
| 200 | 195 |
| 201 | 196 |
| (...skipping 790 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 992 } | 987 } |
| 993 | 988 |
| 994 | 989 |
| 995 // NOTE: If the entry code shape changes, ReturnAddressLocator in profiler.cc | 990 // NOTE: If the entry code shape changes, ReturnAddressLocator in profiler.cc |
| 996 // needs to be updated to match. | 991 // needs to be updated to match. |
| 997 void FlowGraphCompiler::EmitFrameEntry() { | 992 void FlowGraphCompiler::EmitFrameEntry() { |
| 998 const Function& function = parsed_function().function(); | 993 const Function& function = parsed_function().function(); |
| 999 if (CanOptimizeFunction() && | 994 if (CanOptimizeFunction() && |
| 1000 function.IsOptimizable() && | 995 function.IsOptimizable() && |
| 1001 (!is_optimizing() || may_reoptimize())) { | 996 (!is_optimizing() || may_reoptimize())) { |
| 1002 const Register function_reg = EDI; | 997 const Register function_reg = EBX; |
| 1003 __ LoadObject(function_reg, function); | 998 __ LoadObject(function_reg, function); |
| 1004 | 999 |
| 1005 // Patch point is after the eventually inlined function object. | |
| 1006 entry_patch_pc_offset_ = assembler()->CodeSize(); | |
| 1007 | |
| 1008 // Reoptimization of an optimized function is triggered by counting in | 1000 // Reoptimization of an optimized function is triggered by counting in |
| 1009 // IC stubs, but not at the entry of the function. | 1001 // IC stubs, but not at the entry of the function. |
| 1010 if (!is_optimizing()) { | 1002 if (!is_optimizing()) { |
| 1011 __ incl(FieldAddress(function_reg, Function::usage_counter_offset())); | 1003 __ incl(FieldAddress(function_reg, Function::usage_counter_offset())); |
| 1012 } | 1004 } |
| 1013 __ cmpl(FieldAddress(function_reg, Function::usage_counter_offset()), | 1005 __ cmpl(FieldAddress(function_reg, Function::usage_counter_offset()), |
| 1014 Immediate(GetOptimizationThreshold())); | 1006 Immediate(GetOptimizationThreshold())); |
| 1015 ASSERT(function_reg == EDI); | 1007 ASSERT(function_reg == EBX); |
| 1016 __ J(GREATER_EQUAL, *StubCode::OptimizeFunction_entry()); | 1008 __ J(GREATER_EQUAL, *StubCode::OptimizeFunction_entry()); |
| 1017 } else if (!flow_graph().IsCompiledForOsr()) { | |
| 1018 entry_patch_pc_offset_ = assembler()->CodeSize(); | |
| 1019 } | 1009 } |
| 1020 __ Comment("Enter frame"); | 1010 __ Comment("Enter frame"); |
| 1021 if (flow_graph().IsCompiledForOsr()) { | 1011 if (flow_graph().IsCompiledForOsr()) { |
| 1022 intptr_t extra_slots = StackSize() | 1012 intptr_t extra_slots = StackSize() |
| 1023 - flow_graph().num_stack_locals() | 1013 - flow_graph().num_stack_locals() |
| 1024 - flow_graph().num_copied_params(); | 1014 - flow_graph().num_copied_params(); |
| 1025 ASSERT(extra_slots >= 0); | 1015 ASSERT(extra_slots >= 0); |
| 1026 __ EnterOsrFrame(extra_slots * kWordSize); | 1016 __ EnterOsrFrame(extra_slots * kWordSize); |
| 1027 } else { | 1017 } else { |
| 1028 ASSERT(StackSize() >= 0); | 1018 ASSERT(StackSize() >= 0); |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1129 __ movl(Address(EBP, (slot_base - i) * kWordSize), EAX); | 1119 __ movl(Address(EBP, (slot_base - i) * kWordSize), EAX); |
| 1130 } | 1120 } |
| 1131 } | 1121 } |
| 1132 } | 1122 } |
| 1133 | 1123 |
| 1134 ASSERT(!block_order().is_empty()); | 1124 ASSERT(!block_order().is_empty()); |
| 1135 VisitBlocks(); | 1125 VisitBlocks(); |
| 1136 | 1126 |
| 1137 __ int3(); | 1127 __ int3(); |
| 1138 GenerateDeferredCode(); | 1128 GenerateDeferredCode(); |
| 1139 // Emit function patching code. This will be swapped with the first 5 bytes | |
| 1140 // at entry point. | |
| 1141 patch_code_pc_offset_ = assembler()->CodeSize(); | |
| 1142 __ Jmp(*StubCode::FixCallersTarget_entry()); | |
| 1143 | 1129 |
| 1144 if (is_optimizing()) { | 1130 if (is_optimizing()) { |
| 1145 lazy_deopt_pc_offset_ = assembler()->CodeSize(); | 1131 lazy_deopt_pc_offset_ = assembler()->CodeSize(); |
| 1146 __ Jmp(*StubCode::DeoptimizeLazy_entry()); | 1132 __ Jmp(*StubCode::DeoptimizeLazy_entry()); |
| 1147 } | 1133 } |
| 1148 } | 1134 } |
| 1149 | 1135 |
| 1150 | 1136 |
| 1151 void FlowGraphCompiler::GenerateCall(intptr_t token_pos, | 1137 void FlowGraphCompiler::GenerateCall(intptr_t token_pos, |
| 1152 const StubEntry& stub_entry, | 1138 const StubEntry& stub_entry, |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1255 intptr_t deopt_id, | 1241 intptr_t deopt_id, |
| 1256 intptr_t token_pos, | 1242 intptr_t token_pos, |
| 1257 LocationSummary* locs) { | 1243 LocationSummary* locs) { |
| 1258 ASSERT(Array::Handle(ic_data.arguments_descriptor()).Length() > 0); | 1244 ASSERT(Array::Handle(ic_data.arguments_descriptor()).Length() > 0); |
| 1259 // Each ICData propagated from unoptimized to optimized code contains the | 1245 // Each ICData propagated from unoptimized to optimized code contains the |
| 1260 // function that corresponds to the Dart function of that IC call. Due | 1246 // function that corresponds to the Dart function of that IC call. Due |
| 1261 // to inlining in optimized code, that function may not correspond to the | 1247 // to inlining in optimized code, that function may not correspond to the |
| 1262 // top-level function (parsed_function().function()) which could be | 1248 // top-level function (parsed_function().function()) which could be |
| 1263 // reoptimized and which counter needs to be incremented. | 1249 // reoptimized and which counter needs to be incremented. |
| 1264 // Pass the function explicitly, it is used in IC stub. | 1250 // Pass the function explicitly, it is used in IC stub. |
| 1265 __ LoadObject(EDI, parsed_function().function()); | 1251 __ LoadObject(EBX, parsed_function().function()); |
| 1266 __ LoadObject(ECX, ic_data); | 1252 __ LoadObject(ECX, ic_data); |
| 1267 GenerateDartCall(deopt_id, | 1253 GenerateDartCall(deopt_id, |
| 1268 token_pos, | 1254 token_pos, |
| 1269 stub_entry, | 1255 stub_entry, |
| 1270 RawPcDescriptors::kIcCall, | 1256 RawPcDescriptors::kIcCall, |
| 1271 locs); | 1257 locs); |
| 1272 __ Drop(argument_count); | 1258 __ Drop(argument_count); |
| 1273 } | 1259 } |
| 1274 | 1260 |
| 1275 | 1261 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1295 intptr_t argument_count, | 1281 intptr_t argument_count, |
| 1296 intptr_t deopt_id, | 1282 intptr_t deopt_id, |
| 1297 intptr_t token_pos, | 1283 intptr_t token_pos, |
| 1298 LocationSummary* locs) { | 1284 LocationSummary* locs) { |
| 1299 const String& name = String::Handle(zone(), ic_data.target_name()); | 1285 const String& name = String::Handle(zone(), ic_data.target_name()); |
| 1300 const Array& arguments_descriptor = | 1286 const Array& arguments_descriptor = |
| 1301 Array::ZoneHandle(zone(), ic_data.arguments_descriptor()); | 1287 Array::ZoneHandle(zone(), ic_data.arguments_descriptor()); |
| 1302 ASSERT(!arguments_descriptor.IsNull() && (arguments_descriptor.Length() > 0)); | 1288 ASSERT(!arguments_descriptor.IsNull() && (arguments_descriptor.Length() > 0)); |
| 1303 const MegamorphicCache& cache = MegamorphicCache::ZoneHandle(zone(), | 1289 const MegamorphicCache& cache = MegamorphicCache::ZoneHandle(zone(), |
| 1304 MegamorphicCacheTable::Lookup(isolate(), name, arguments_descriptor)); | 1290 MegamorphicCacheTable::Lookup(isolate(), name, arguments_descriptor)); |
| 1305 const Register receiverR = EDI; | 1291 const Register receiverR = ECX; |
| 1306 const Register cacheR = EBX; | 1292 const Register cacheR = EBX; |
| 1307 const Register targetR = EBX; | 1293 const Register targetR = EBX; |
| 1308 __ movl(receiverR, Address(ESP, (argument_count - 1) * kWordSize)); | 1294 __ movl(receiverR, Address(ESP, (argument_count - 1) * kWordSize)); |
| 1309 __ LoadObject(cacheR, cache); | 1295 __ LoadObject(cacheR, cache); |
| 1310 | 1296 |
| 1311 if (FLAG_use_megamorphic_stub) { | 1297 if (FLAG_use_megamorphic_stub) { |
| 1312 __ Call(*StubCode::MegamorphicLookup_entry()); | 1298 __ Call(*StubCode::MegamorphicLookup_entry()); |
| 1313 } else { | 1299 } else { |
| 1314 StubCode::EmitMegamorphicLookup(assembler(), receiverR, cacheR, targetR); | 1300 StubCode::EmitMegamorphicLookup(assembler(), receiverR, cacheR, targetR); |
| 1315 } | 1301 } |
| (...skipping 531 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1847 __ movups(reg, Address(ESP, 0)); | 1833 __ movups(reg, Address(ESP, 0)); |
| 1848 __ addl(ESP, Immediate(kFpuRegisterSize)); | 1834 __ addl(ESP, Immediate(kFpuRegisterSize)); |
| 1849 } | 1835 } |
| 1850 | 1836 |
| 1851 | 1837 |
| 1852 #undef __ | 1838 #undef __ |
| 1853 | 1839 |
| 1854 } // namespace dart | 1840 } // namespace dart |
| 1855 | 1841 |
| 1856 #endif // defined TARGET_ARCH_IA32 | 1842 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |