| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 "lib/error.h" | 10 #include "lib/error.h" |
| (...skipping 21 matching lines...) Expand all Loading... |
| 32 | 32 |
| 33 if (deoptimization_env_ == NULL) { | 33 if (deoptimization_env_ == NULL) { |
| 34 for (intptr_t i = 0; i < registers_.length(); i++) { | 34 for (intptr_t i = 0; i < registers_.length(); i++) { |
| 35 if (registers_[i] != kNoRegister) { | 35 if (registers_[i] != kNoRegister) { |
| 36 __ pushq(registers_[i]); | 36 __ pushq(registers_[i]); |
| 37 } | 37 } |
| 38 } | 38 } |
| 39 } else { | 39 } else { |
| 40 // We have a deoptimization environment, we have to tear down the | 40 // We have a deoptimization environment, we have to tear down the |
| 41 // optimized frame and recreate a non-optimized one. | 41 // optimized frame and recreate a non-optimized one. |
| 42 const intptr_t fixed_parameter_count = |
| 43 deoptimization_env_->fixed_parameter_count(); |
| 42 | 44 |
| 43 // 1. Set the stack pointer to the top of the non-optimized frame. | 45 // 1. Set the stack pointer to the top of the non-optimized frame. |
| 44 const GrowableArray<Value*>& values = deoptimization_env_->values(); | 46 const GrowableArray<Value*>& values = deoptimization_env_->values(); |
| 47 const intptr_t local_slot_count = values.length() - fixed_parameter_count; |
| 45 const intptr_t top_offset = | 48 const intptr_t top_offset = |
| 46 ParsedFunction::kFirstLocalSlotIndex - values.length(); | 49 ParsedFunction::kFirstLocalSlotIndex - (local_slot_count - 1); |
| 47 __ leaq(RSP, Address(RBP, top_offset * kWordSize)); | 50 __ leaq(RSP, Address(RBP, top_offset * kWordSize)); |
| 48 | 51 |
| 49 // 2. Build and emit a parallel move representing the frame translation. | 52 // 2. Build and emit a parallel move representing the frame translation. |
| 50 ParallelMoveInstr* move = new ParallelMoveInstr(); | 53 ParallelMoveInstr* move = new ParallelMoveInstr(); |
| 51 for (intptr_t i = 0; i < values.length(); i++) { | 54 for (intptr_t i = 0; i < values.length(); i++) { |
| 52 Location destination = Location::SpillSlot(i); | 55 Location destination = Location::StackSlot(i - fixed_parameter_count); |
| 53 Location source = deoptimization_env_->LocationAt(i); | 56 Location source = deoptimization_env_->LocationAt(i); |
| 54 if (!source.IsRegister() && !source.IsInvalid()) { | 57 if (!source.IsRegister() && !source.IsInvalid()) { |
| 55 compiler->Bailout("unsupported deoptimization state"); | 58 compiler->Bailout("unsupported deoptimization state"); |
| 56 } | 59 } |
| 57 if (source.IsInvalid()) { | 60 if (source.IsInvalid()) { |
| 58 ASSERT(values[i]->IsConstant()); | 61 ASSERT(values[i]->IsConstant()); |
| 59 source = Location::Constant(values[i]->AsConstant()->value()); | 62 source = Location::Constant(values[i]->AsConstant()->value()); |
| 60 } | 63 } |
| 61 move->AddMove(destination, source); | 64 move->AddMove(destination, source); |
| 62 } | 65 } |
| (...skipping 897 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 960 CatchClauseNode::kInvalidTryIndex, | 963 CatchClauseNode::kInvalidTryIndex, |
| 961 kClosureArgumentMismatchRuntimeEntry); | 964 kClosureArgumentMismatchRuntimeEntry); |
| 962 } else { | 965 } else { |
| 963 __ Stop("Wrong number of arguments"); | 966 __ Stop("Wrong number of arguments"); |
| 964 } | 967 } |
| 965 __ Bind(&argc_in_range); | 968 __ Bind(&argc_in_range); |
| 966 } | 969 } |
| 967 } else { | 970 } else { |
| 968 CopyParameters(); | 971 CopyParameters(); |
| 969 } | 972 } |
| 973 |
| 974 // TODO(vegorov): introduce stack maps and stop initializing all spill slots |
| 975 // with null. |
| 976 const intptr_t stack_slot_count = |
| 977 is_ssa_ ? block_order_[0]->AsGraphEntry()->spill_slot_count() |
| 978 : local_count; |
| 979 |
| 980 const intptr_t slot_base = parsed_function().first_stack_local_index(); |
| 981 |
| 970 // Initialize (non-argument) stack allocated locals to null. | 982 // Initialize (non-argument) stack allocated locals to null. |
| 971 if (local_count > 0) { | 983 if (stack_slot_count > 0) { |
| 972 const Immediate raw_null = | 984 const Immediate raw_null = |
| 973 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 985 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 974 __ movq(RAX, raw_null); | 986 __ movq(RAX, raw_null); |
| 975 const int base = parsed_function().first_stack_local_index(); | 987 for (intptr_t i = 0; i < stack_slot_count; ++i) { |
| 976 for (int i = 0; i < local_count; ++i) { | |
| 977 // Subtract index i (locals lie at lower addresses than RBP). | 988 // Subtract index i (locals lie at lower addresses than RBP). |
| 978 __ movq(Address(RBP, (base - i) * kWordSize), RAX); | 989 __ movq(Address(RBP, (slot_base - i) * kWordSize), RAX); |
| 979 } | 990 } |
| 980 } | 991 } |
| 981 | 992 |
| 982 if (!IsLeaf()) { | 993 if (!IsLeaf()) { |
| 983 // Generate stack overflow check. | 994 // Generate stack overflow check. |
| 984 __ movq(RDI, Immediate(Isolate::Current()->stack_limit_address())); | 995 __ movq(RDI, Immediate(Isolate::Current()->stack_limit_address())); |
| 985 __ cmpq(RSP, Address(RDI, 0)); | 996 __ cmpq(RSP, Address(RDI, 0)); |
| 986 Label no_stack_overflow; | 997 Label no_stack_overflow; |
| 987 __ j(ABOVE, &no_stack_overflow, Assembler::kNearJump); | 998 __ j(ABOVE, &no_stack_overflow, Assembler::kNearJump); |
| 988 GenerateCallRuntime(AstNode::kNoId, | 999 GenerateCallRuntime(AstNode::kNoId, |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1112 __ SmiUntag(temp); | 1123 __ SmiUntag(temp); |
| 1113 __ cvtsi2sd(result, temp); | 1124 __ cvtsi2sd(result, temp); |
| 1114 __ Bind(&done); | 1125 __ Bind(&done); |
| 1115 } | 1126 } |
| 1116 | 1127 |
| 1117 | 1128 |
| 1118 #undef __ | 1129 #undef __ |
| 1119 #define __ compiler_->assembler()-> | 1130 #define __ compiler_->assembler()-> |
| 1120 | 1131 |
| 1121 | 1132 |
| 1122 static Address ToAddress(Location loc) { | 1133 static Address ToStackSlotAddress(Location loc) { |
| 1123 ASSERT(loc.IsSpillSlot()); | 1134 ASSERT(loc.IsStackSlot()); |
| 1124 const intptr_t offset = | 1135 const intptr_t index = loc.stack_index(); |
| 1125 (ParsedFunction::kFirstLocalSlotIndex - loc.spill_index()) * kWordSize; | 1136 if (index < 0) { |
| 1126 return Address(RBP, offset); | 1137 const intptr_t offset = (1 - index) * kWordSize; |
| 1138 return Address(RBP, offset); |
| 1139 } else { |
| 1140 const intptr_t offset = |
| 1141 (ParsedFunction::kFirstLocalSlotIndex - index) * kWordSize; |
| 1142 return Address(RBP, offset); |
| 1143 } |
| 1127 } | 1144 } |
| 1128 | 1145 |
| 1129 | 1146 |
| 1130 void ParallelMoveResolver::EmitMove(int index) { | 1147 void ParallelMoveResolver::EmitMove(int index) { |
| 1131 MoveOperands* move = moves_[index]; | 1148 MoveOperands* move = moves_[index]; |
| 1132 const Location source = move->src(); | 1149 const Location source = move->src(); |
| 1133 const Location destination = move->dest(); | 1150 const Location destination = move->dest(); |
| 1134 | 1151 |
| 1135 if (source.IsRegister()) { | 1152 if (source.IsRegister()) { |
| 1136 if (destination.IsRegister()) { | 1153 if (destination.IsRegister()) { |
| 1137 __ movq(destination.reg(), source.reg()); | 1154 __ movq(destination.reg(), source.reg()); |
| 1138 } else { | 1155 } else { |
| 1139 ASSERT(destination.IsSpillSlot()); | 1156 ASSERT(destination.IsStackSlot()); |
| 1140 __ movq(ToAddress(destination), source.reg()); | 1157 __ movq(ToStackSlotAddress(destination), source.reg()); |
| 1141 } | 1158 } |
| 1142 } else if (source.IsSpillSlot()) { | 1159 } else if (source.IsStackSlot()) { |
| 1143 if (destination.IsRegister()) { | 1160 if (destination.IsRegister()) { |
| 1144 __ movq(destination.reg(), ToAddress(source)); | 1161 __ movq(destination.reg(), ToStackSlotAddress(source)); |
| 1145 } else { | 1162 } else { |
| 1146 ASSERT(destination.IsSpillSlot()); | 1163 ASSERT(destination.IsStackSlot()); |
| 1147 MoveMemoryToMemory(ToAddress(destination), ToAddress(source)); | 1164 MoveMemoryToMemory(ToStackSlotAddress(destination), |
| 1165 ToStackSlotAddress(source)); |
| 1148 } | 1166 } |
| 1149 } else { | 1167 } else { |
| 1150 ASSERT(source.IsConstant()); | 1168 ASSERT(source.IsConstant()); |
| 1151 if (destination.IsRegister()) { | 1169 if (destination.IsRegister()) { |
| 1152 __ LoadObject(destination.reg(), source.constant()); | 1170 __ LoadObject(destination.reg(), source.constant()); |
| 1153 } else { | 1171 } else { |
| 1154 ASSERT(destination.IsSpillSlot()); | 1172 ASSERT(destination.IsStackSlot()); |
| 1155 StoreObject(ToAddress(destination), source.constant()); | 1173 StoreObject(ToStackSlotAddress(destination), source.constant()); |
| 1156 } | 1174 } |
| 1157 } | 1175 } |
| 1158 | 1176 |
| 1159 move->Eliminate(); | 1177 move->Eliminate(); |
| 1160 } | 1178 } |
| 1161 | 1179 |
| 1162 | 1180 |
| 1163 void ParallelMoveResolver::EmitSwap(int index) { | 1181 void ParallelMoveResolver::EmitSwap(int index) { |
| 1164 MoveOperands* move = moves_[index]; | 1182 MoveOperands* move = moves_[index]; |
| 1165 const Location source = move->src(); | 1183 const Location source = move->src(); |
| 1166 const Location destination = move->dest(); | 1184 const Location destination = move->dest(); |
| 1167 | 1185 |
| 1168 if (source.IsRegister() && destination.IsRegister()) { | 1186 if (source.IsRegister() && destination.IsRegister()) { |
| 1169 __ xchgq(destination.reg(), source.reg()); | 1187 __ xchgq(destination.reg(), source.reg()); |
| 1170 } else if (source.IsRegister() && destination.IsSpillSlot()) { | 1188 } else if (source.IsRegister() && destination.IsStackSlot()) { |
| 1171 Exchange(source.reg(), ToAddress(destination)); | 1189 Exchange(source.reg(), ToStackSlotAddress(destination)); |
| 1172 } else if (source.IsSpillSlot() && destination.IsRegister()) { | 1190 } else if (source.IsStackSlot() && destination.IsRegister()) { |
| 1173 Exchange(destination.reg(), ToAddress(source)); | 1191 Exchange(destination.reg(), ToStackSlotAddress(source)); |
| 1174 } else if (source.IsSpillSlot() && destination.IsSpillSlot()) { | 1192 } else if (source.IsStackSlot() && destination.IsStackSlot()) { |
| 1175 Exchange(ToAddress(destination), ToAddress(source)); | 1193 Exchange(ToStackSlotAddress(destination), ToStackSlotAddress(source)); |
| 1176 } else { | 1194 } else { |
| 1177 UNREACHABLE(); | 1195 UNREACHABLE(); |
| 1178 } | 1196 } |
| 1179 | 1197 |
| 1180 // The swap of source and destination has executed a move from source to | 1198 // The swap of source and destination has executed a move from source to |
| 1181 // destination. | 1199 // destination. |
| 1182 move->Eliminate(); | 1200 move->Eliminate(); |
| 1183 | 1201 |
| 1184 // Any unperformed (including pending) move with a source of either | 1202 // Any unperformed (including pending) move with a source of either |
| 1185 // this move's source or destination needs to have their source | 1203 // this move's source or destination needs to have their source |
| (...skipping 28 matching lines...) Expand all Loading... |
| 1214 void ParallelMoveResolver::Exchange(const Address& mem1, const Address& mem2) { | 1232 void ParallelMoveResolver::Exchange(const Address& mem1, const Address& mem2) { |
| 1215 __ Exchange(mem1, mem2); | 1233 __ Exchange(mem1, mem2); |
| 1216 } | 1234 } |
| 1217 | 1235 |
| 1218 | 1236 |
| 1219 #undef __ | 1237 #undef __ |
| 1220 | 1238 |
| 1221 } // namespace dart | 1239 } // namespace dart |
| 1222 | 1240 |
| 1223 #endif // defined TARGET_ARCH_X64 | 1241 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |