Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | |
| 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. | |
| 4 | |
| 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_DBC. | |
| 6 #if defined(TARGET_ARCH_DBC) | |
| 7 | |
| 8 #include "vm/flow_graph_compiler.h" | |
| 9 | |
| 10 #include "vm/ast_printer.h" | |
| 11 #include "vm/compiler.h" | |
| 12 #include "vm/cpu.h" | |
| 13 #include "vm/dart_entry.h" | |
| 14 #include "vm/deopt_instructions.h" | |
| 15 #include "vm/il_printer.h" | |
| 16 #include "vm/instructions.h" | |
| 17 #include "vm/locations.h" | |
| 18 #include "vm/object_store.h" | |
| 19 #include "vm/parser.h" | |
| 20 #include "vm/stack_frame.h" | |
| 21 #include "vm/stub_code.h" | |
| 22 #include "vm/symbols.h" | |
| 23 #include "vm/verified_memory.h" | |
| 24 | |
| 25 namespace dart { | |
| 26 | |
| 27 DEFINE_FLAG(bool, trap_on_deoptimization, false, "Trap on deoptimization."); | |
| 28 DEFINE_FLAG(bool, unbox_mints, true, "Optimize 64-bit integer arithmetic."); | |
| 29 DEFINE_FLAG(bool, unbox_doubles, true, "Optimize double arithmetic."); | |
| 30 DECLARE_FLAG(bool, enable_simd_inline); | |
| 31 DECLARE_FLAG(bool, use_megamorphic_stub); | |
| 32 DECLARE_FLAG(charp, optimization_filter); | |
| 33 | |
| 34 void MegamorphicSlowPath::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 35 #define __ assembler-> | |
| 36 UNIMPLEMENTED(); | |
| 37 #undef __ | |
| 38 } | |
| 39 | |
| 40 | |
| 41 FlowGraphCompiler::~FlowGraphCompiler() { | |
| 42 // BlockInfos are zone-allocated, so their destructors are not called. | |
| 43 // Verify the labels explicitly here. | |
| 44 for (int i = 0; i < block_info_.length(); ++i) { | |
| 45 ASSERT(!block_info_[i]->jump_label()->IsLinked()); | |
| 46 } | |
| 47 } | |
| 48 | |
| 49 | |
| 50 bool FlowGraphCompiler::SupportsUnboxedDoubles() { | |
| 51 return false; | |
| 52 } | |
| 53 | |
| 54 | |
| 55 bool FlowGraphCompiler::SupportsUnboxedMints() { | |
| 56 return false; | |
| 57 } | |
| 58 | |
| 59 | |
| 60 bool FlowGraphCompiler::SupportsUnboxedSimd128() { | |
| 61 return false; | |
| 62 } | |
| 63 | |
| 64 | |
| 65 bool FlowGraphCompiler::SupportsSinCos() { | |
| 66 return false; | |
| 67 } | |
| 68 | |
| 69 | |
| 70 bool FlowGraphCompiler::SupportsHardwareDivision() { | |
| 71 return true; | |
| 72 } | |
| 73 | |
| 74 | |
| 75 bool FlowGraphCompiler::CanConvertUnboxedMintToDouble() { | |
| 76 return false; | |
| 77 } | |
| 78 | |
| 79 | |
| 80 void FlowGraphCompiler::EnterIntrinsicMode() { | |
| 81 ASSERT(!intrinsic_mode()); | |
| 82 intrinsic_mode_ = true; | |
| 83 } | |
| 84 | |
| 85 | |
| 86 void FlowGraphCompiler::ExitIntrinsicMode() { | |
| 87 ASSERT(intrinsic_mode()); | |
| 88 intrinsic_mode_ = false; | |
| 89 } | |
| 90 | |
| 91 | |
| 92 RawTypedData* CompilerDeoptInfo::CreateDeoptInfo(FlowGraphCompiler* compiler, | |
| 93 DeoptInfoBuilder* builder, | |
| 94 const Array& deopt_table) { | |
| 95 UNIMPLEMENTED(); | |
| 96 return TypedData::null(); | |
| 97 } | |
| 98 | |
| 99 | |
| 100 void CompilerDeoptInfoWithStub::GenerateCode(FlowGraphCompiler* compiler, | |
| 101 intptr_t stub_ix) { | |
| 102 // Calls do not need stubs, they share a deoptimization trampoline. | |
| 103 ASSERT(reason() != ICData::kDeoptAtCall); | |
| 104 #define __ assembler-> | |
| 105 UNIMPLEMENTED(); | |
| 106 #undef __ | |
| 107 } | |
| 108 | |
| 109 | |
| 110 #define __ assembler()-> | |
| 111 | |
| 112 | |
| 113 void FlowGraphCompiler::GenerateAssertAssignable(TokenPosition token_pos, | |
| 114 intptr_t deopt_id, | |
| 115 const AbstractType& dst_type, | |
| 116 const String& dst_name, | |
| 117 LocationSummary* locs) { | |
| 118 ASSERT(!is_optimizing()); | |
| 119 SubtypeTestCache& test_cache = SubtypeTestCache::Handle(); | |
| 120 if (!dst_type.IsVoidType() && dst_type.IsInstantiated()) { | |
| 121 test_cache = SubtypeTestCache::New(); | |
| 122 } | |
| 123 | |
| 124 __ PushConstant(dst_type); | |
| 125 __ PushConstant(dst_name); | |
| 126 __ AssertAssignable(__ AddConstant(test_cache)); | |
| 127 AddCurrentDescriptor(RawPcDescriptors::kOther, deopt_id, token_pos); | |
| 128 } | |
| 129 | |
| 130 | |
| 131 void FlowGraphCompiler::EmitInstructionEpilogue(Instruction* instr) { | |
| 132 if (!is_optimizing()) { | |
| 133 Definition* defn = instr->AsDefinition(); | |
| 134 if ((defn != NULL) && | |
| 135 (defn->tag() != Instruction::kPushArgument) && | |
| 136 (defn->tag() != Instruction::kStoreIndexed) && | |
| 137 (defn->tag() != Instruction::kStoreStaticField) && | |
| 138 (defn->tag() != Instruction::kStoreLocal) && | |
| 139 (defn->tag() != Instruction::kStoreInstanceField) && | |
| 140 (defn->tag() != Instruction::kDropTemps) && | |
| 141 (defn->tag() != Instruction::kPushTemp) && | |
| 142 !defn->HasTemp()) { | |
| 143 __ Drop1(); | |
| 144 } | |
| 145 } | |
| 146 } | |
| 147 | |
| 148 | |
| 149 void FlowGraphCompiler::GenerateInlinedGetter(intptr_t offset) { | |
| 150 __ Move(0, -(1 + kParamEndSlotFromFp)); | |
| 151 __ LoadField(0, 0, offset / kWordSize); | |
| 152 __ Return(0); | |
| 153 } | |
| 154 | |
| 155 | |
| 156 void FlowGraphCompiler::GenerateInlinedSetter(intptr_t offset) { | |
| 157 __ Move(0, -(2 + kParamEndSlotFromFp)); | |
| 158 __ Move(1, -(1 + kParamEndSlotFromFp)); | |
| 159 __ StoreField(0, offset / kWordSize, 1); | |
| 160 __ LoadConstant(0, Object::Handle()); | |
| 161 __ Return(0); | |
| 162 } | |
| 163 | |
| 164 | |
| 165 void FlowGraphCompiler::EmitFrameEntry() { | |
| 166 const Function& function = parsed_function().function(); | |
| 167 const intptr_t num_fixed_params = function.num_fixed_parameters(); | |
| 168 const int num_opt_pos_params = function.NumOptionalPositionalParameters(); | |
| 169 const int num_opt_named_params = function.NumOptionalNamedParameters(); | |
| 170 const int num_params = | |
| 171 num_fixed_params + num_opt_pos_params + num_opt_named_params; | |
| 172 const bool has_optional_params = num_opt_pos_params != 0 || | |
| 173 num_opt_named_params != 0; | |
| 174 const int num_locals = parsed_function().num_stack_locals(); | |
| 175 const intptr_t context_index = | |
| 176 -parsed_function().current_context_var()->index() - 1; | |
| 177 | |
| 178 if (has_optional_params) { | |
| 179 __ EntryOpt(num_fixed_params, num_opt_pos_params, num_opt_named_params); | |
| 180 } else { | |
| 181 __ Entry(num_fixed_params, num_locals, context_index); | |
| 182 } | |
| 183 | |
| 184 if (num_opt_named_params != 0) { | |
| 185 LocalScope* scope = parsed_function().node_sequence()->scope(); | |
| 186 | |
| 187 // Start by alphabetically sorting the names of the optional parameters. | |
| 188 LocalVariable** opt_param = new LocalVariable*[num_opt_named_params]; | |
| 189 int* opt_param_position = new int[num_opt_named_params]; | |
| 190 for (int pos = num_fixed_params; pos < num_params; pos++) { | |
| 191 LocalVariable* parameter = scope->VariableAt(pos); | |
| 192 const String& opt_param_name = parameter->name(); | |
| 193 int i = pos - num_fixed_params; | |
| 194 while (--i >= 0) { | |
| 195 LocalVariable* param_i = opt_param[i]; | |
| 196 const intptr_t result = opt_param_name.CompareTo(param_i->name()); | |
| 197 ASSERT(result != 0); | |
| 198 if (result > 0) break; | |
| 199 opt_param[i + 1] = opt_param[i]; | |
| 200 opt_param_position[i + 1] = opt_param_position[i]; | |
| 201 } | |
| 202 opt_param[i + 1] = parameter; | |
| 203 opt_param_position[i + 1] = pos; | |
| 204 } | |
| 205 | |
| 206 for (intptr_t i = 0; i < num_opt_named_params; i++) { | |
| 207 const int param_pos = opt_param_position[i]; | |
| 208 const Instance& value = parsed_function().DefaultParameterValueAt( | |
| 209 param_pos - num_fixed_params); | |
| 210 __ LoadConstant(param_pos, opt_param[i]->name()); | |
| 211 __ LoadConstant(param_pos, value); | |
| 212 } | |
|
Florian Schneider
2016/04/12 18:01:42
delete[] opt_param;
delete[] opt_param_position;
Vyacheslav Egorov (Google)
2016/04/14 13:05:27
Switched to Zone allocation.
| |
| 213 } else if (num_opt_pos_params != 0) { | |
| 214 for (intptr_t i = 0; i < num_opt_pos_params; i++) { | |
| 215 const Object& value = parsed_function().DefaultParameterValueAt(i); | |
| 216 __ LoadConstant(num_fixed_params + i, value); | |
| 217 } | |
| 218 } | |
| 219 | |
| 220 | |
| 221 ASSERT(num_locals > 0); // There is always at least context_var. | |
| 222 if (has_optional_params) { | |
| 223 ASSERT(!is_optimizing()); | |
| 224 __ Frame(num_locals); // Reserve space for locals. | |
| 225 } | |
| 226 | |
| 227 if (function.IsClosureFunction()) { | |
| 228 Register reg = context_index; | |
| 229 Register closure_reg = reg; | |
| 230 LocalScope* scope = parsed_function().node_sequence()->scope(); | |
| 231 LocalVariable* local = scope->VariableAt(0); | |
| 232 if (local->index() > 0) { | |
| 233 __ Move(reg, -local->index()); | |
| 234 } else { | |
| 235 closure_reg = -local->index() - 1; | |
| 236 } | |
| 237 __ LoadField(reg, closure_reg, Closure::context_offset() / kWordSize); | |
| 238 } else if (has_optional_params) { | |
| 239 __ LoadConstant(context_index, | |
| 240 Object::Handle(isolate()->object_store()->empty_context())); | |
| 241 } | |
| 242 } | |
| 243 | |
| 244 | |
| 245 void FlowGraphCompiler::CompileGraph() { | |
| 246 InitCompiler(); | |
| 247 | |
| 248 if (TryIntrinsify()) { | |
| 249 // Skip regular code generation. | |
| 250 return; | |
| 251 } | |
| 252 | |
| 253 EmitFrameEntry(); | |
| 254 VisitBlocks(); | |
| 255 } | |
| 256 | |
| 257 | |
| 258 #undef __ | |
| 259 #define __ compiler_->assembler()-> | |
| 260 | |
| 261 | |
| 262 void ParallelMoveResolver::EmitMove(int index) { | |
| 263 UNIMPLEMENTED(); | |
| 264 } | |
| 265 | |
| 266 | |
| 267 void ParallelMoveResolver::EmitSwap(int index) { | |
| 268 UNIMPLEMENTED(); | |
| 269 } | |
| 270 | |
| 271 | |
| 272 void ParallelMoveResolver::MoveMemoryToMemory(const Address& dst, | |
| 273 const Address& src) { | |
| 274 UNREACHABLE(); | |
| 275 } | |
| 276 | |
| 277 | |
| 278 void ParallelMoveResolver::StoreObject(const Address& dst, const Object& obj) { | |
| 279 UNREACHABLE(); | |
| 280 } | |
| 281 | |
| 282 | |
| 283 // Do not call or implement this function. Instead, use the form below that | |
| 284 // uses an offset from the frame pointer instead of an Address. | |
| 285 void ParallelMoveResolver::Exchange(Register reg, const Address& mem) { | |
| 286 UNREACHABLE(); | |
| 287 } | |
| 288 | |
| 289 | |
| 290 // Do not call or implement this function. Instead, use the form below that | |
| 291 // uses offsets from the frame pointer instead of Addresses. | |
| 292 void ParallelMoveResolver::Exchange(const Address& mem1, const Address& mem2) { | |
| 293 UNREACHABLE(); | |
| 294 } | |
| 295 | |
| 296 | |
| 297 void ParallelMoveResolver::Exchange(Register reg, | |
| 298 Register base_reg, | |
| 299 intptr_t stack_offset) { | |
| 300 UNIMPLEMENTED(); | |
| 301 } | |
| 302 | |
| 303 | |
| 304 void ParallelMoveResolver::Exchange(Register base_reg1, | |
| 305 intptr_t stack_offset1, | |
| 306 Register base_reg2, | |
| 307 intptr_t stack_offset2) { | |
| 308 UNIMPLEMENTED(); | |
| 309 } | |
| 310 | |
| 311 | |
| 312 void ParallelMoveResolver::SpillScratch(Register reg) { | |
| 313 UNIMPLEMENTED(); | |
| 314 } | |
| 315 | |
| 316 | |
| 317 void ParallelMoveResolver::RestoreScratch(Register reg) { | |
| 318 UNIMPLEMENTED(); | |
| 319 } | |
| 320 | |
| 321 | |
| 322 void ParallelMoveResolver::SpillFpuScratch(FpuRegister reg) { | |
| 323 UNIMPLEMENTED(); | |
| 324 } | |
| 325 | |
| 326 | |
| 327 void ParallelMoveResolver::RestoreFpuScratch(FpuRegister reg) { | |
| 328 UNIMPLEMENTED(); | |
| 329 } | |
| 330 | |
| 331 | |
| 332 #undef __ | |
| 333 | |
| 334 } // namespace dart | |
| 335 | |
| 336 #endif // defined TARGET_ARCH_DBC | |
| OLD | NEW |