| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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_ARM64. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM64. |
| 6 #if defined(TARGET_ARCH_ARM64) | 6 #if defined(TARGET_ARCH_ARM64) |
| 7 | 7 |
| 8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
| 9 | 9 |
| 10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
| 11 #include "vm/flow_graph_compiler.h" | 11 #include "vm/flow_graph_compiler.h" |
| 12 #include "vm/locations.h" | 12 #include "vm/locations.h" |
| 13 #include "vm/object_store.h" | 13 #include "vm/object_store.h" |
| 14 #include "vm/parser.h" | 14 #include "vm/parser.h" |
| 15 #include "vm/simulator.h" | 15 #include "vm/simulator.h" |
| 16 #include "vm/stack_frame.h" | 16 #include "vm/stack_frame.h" |
| 17 #include "vm/stub_code.h" | 17 #include "vm/stub_code.h" |
| 18 #include "vm/symbols.h" | 18 #include "vm/symbols.h" |
| 19 | 19 |
| 20 #define __ compiler->assembler()-> | 20 #define __ compiler->assembler()-> |
| 21 | 21 |
| 22 namespace dart { | 22 namespace dart { |
| 23 | 23 |
| 24 DECLARE_FLAG(int, optimization_counter_threshold); |
| 25 DECLARE_FLAG(bool, use_osr); |
| 26 |
| 24 LocationSummary* Instruction::MakeCallSummary() { | 27 LocationSummary* Instruction::MakeCallSummary() { |
| 25 UNIMPLEMENTED(); | 28 UNIMPLEMENTED(); |
| 26 return NULL; | 29 return NULL; |
| 27 } | 30 } |
| 28 | 31 |
| 29 | 32 |
| 30 LocationSummary* PushArgumentInstr::MakeLocationSummary(bool opt) const { | 33 LocationSummary* PushArgumentInstr::MakeLocationSummary(bool opt) const { |
| 31 UNIMPLEMENTED(); | 34 UNIMPLEMENTED(); |
| 32 return NULL; | 35 return NULL; |
| 33 } | 36 } |
| 34 | 37 |
| 35 | 38 |
| 36 void PushArgumentInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 39 void PushArgumentInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 37 UNIMPLEMENTED(); | 40 UNIMPLEMENTED(); |
| 38 } | 41 } |
| 39 | 42 |
| 40 | 43 |
| 41 LocationSummary* ReturnInstr::MakeLocationSummary(bool opt) const { | 44 LocationSummary* ReturnInstr::MakeLocationSummary(bool opt) const { |
| 42 UNIMPLEMENTED(); | 45 const intptr_t kNumInputs = 1; |
| 43 return NULL; | 46 const intptr_t kNumTemps = 0; |
| 47 LocationSummary* locs = |
| 48 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 49 locs->set_in(0, Location::RegisterLocation(R0)); |
| 50 return locs; |
| 44 } | 51 } |
| 45 | 52 |
| 46 | 53 |
| 54 // Attempt optimized compilation at return instruction instead of at the entry. |
| 55 // The entry needs to be patchable, no inlined objects are allowed in the area |
| 56 // that will be overwritten by the patch instructions: a branch macro sequence. |
| 47 void ReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 57 void ReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 48 UNIMPLEMENTED(); | 58 Register result = locs()->in(0).reg(); |
| 59 ASSERT(result == R0); |
| 60 #if defined(DEBUG) |
| 61 Label stack_ok; |
| 62 __ Comment("Stack Check"); |
| 63 const intptr_t fp_sp_dist = |
| 64 (kFirstLocalSlotFromFp + 1 - compiler->StackSize()) * kWordSize; |
| 65 ASSERT(fp_sp_dist <= 0); |
| 66 // UXTX 0 on a 64-bit register (FP) is a nop, but forces R31 to be |
| 67 // interpreted as SP. |
| 68 __ sub(R2, SP, Operand(FP, UXTX, 0)); |
| 69 __ CompareImmediate(R2, fp_sp_dist, PP); |
| 70 __ b(&stack_ok, EQ); |
| 71 __ hlt(0); |
| 72 __ Bind(&stack_ok); |
| 73 #endif |
| 74 __ LeaveDartFrame(); |
| 75 __ ret(); |
| 49 } | 76 } |
| 50 | 77 |
| 51 | 78 |
| 52 LocationSummary* IfThenElseInstr::MakeLocationSummary(bool opt) const { | 79 LocationSummary* IfThenElseInstr::MakeLocationSummary(bool opt) const { |
| 53 UNIMPLEMENTED(); | 80 UNIMPLEMENTED(); |
| 54 return NULL; | 81 return NULL; |
| 55 } | 82 } |
| 56 | 83 |
| 57 | 84 |
| 58 void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 85 void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| (...skipping 28 matching lines...) Expand all Loading... |
| 87 return NULL; | 114 return NULL; |
| 88 } | 115 } |
| 89 | 116 |
| 90 | 117 |
| 91 void StoreLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 118 void StoreLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 92 UNIMPLEMENTED(); | 119 UNIMPLEMENTED(); |
| 93 } | 120 } |
| 94 | 121 |
| 95 | 122 |
| 96 LocationSummary* ConstantInstr::MakeLocationSummary(bool opt) const { | 123 LocationSummary* ConstantInstr::MakeLocationSummary(bool opt) const { |
| 97 UNIMPLEMENTED(); | 124 return LocationSummary::Make(0, |
| 98 return NULL; | 125 Location::RequiresRegister(), |
| 126 LocationSummary::kNoCall); |
| 99 } | 127 } |
| 100 | 128 |
| 101 | 129 |
| 102 void ConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 130 void ConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 103 UNIMPLEMENTED(); | 131 // The register allocator drops constant definitions that have no uses. |
| 132 if (!locs()->out(0).IsInvalid()) { |
| 133 Register result = locs()->out(0).reg(); |
| 134 __ LoadObject(result, value(), PP); |
| 135 } |
| 104 } | 136 } |
| 105 | 137 |
| 106 | 138 |
| 107 LocationSummary* AssertAssignableInstr::MakeLocationSummary(bool opt) const { | 139 LocationSummary* AssertAssignableInstr::MakeLocationSummary(bool opt) const { |
| 108 UNIMPLEMENTED(); | 140 UNIMPLEMENTED(); |
| 109 return NULL; | 141 return NULL; |
| 110 } | 142 } |
| 111 | 143 |
| 112 | 144 |
| 113 LocationSummary* AssertBooleanInstr::MakeLocationSummary(bool opt) const { | 145 LocationSummary* AssertBooleanInstr::MakeLocationSummary(bool opt) const { |
| (...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 427 return NULL; | 459 return NULL; |
| 428 } | 460 } |
| 429 | 461 |
| 430 | 462 |
| 431 void CatchBlockEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 463 void CatchBlockEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 432 UNIMPLEMENTED(); | 464 UNIMPLEMENTED(); |
| 433 } | 465 } |
| 434 | 466 |
| 435 | 467 |
| 436 LocationSummary* CheckStackOverflowInstr::MakeLocationSummary(bool opt) const { | 468 LocationSummary* CheckStackOverflowInstr::MakeLocationSummary(bool opt) const { |
| 437 UNIMPLEMENTED(); | 469 const intptr_t kNumInputs = 0; |
| 438 return NULL; | 470 const intptr_t kNumTemps = 1; |
| 471 LocationSummary* summary = |
| 472 new LocationSummary(kNumInputs, |
| 473 kNumTemps, |
| 474 LocationSummary::kCallOnSlowPath); |
| 475 summary->set_temp(0, Location::RequiresRegister()); |
| 476 return summary; |
| 439 } | 477 } |
| 440 | 478 |
| 441 | 479 |
| 480 class CheckStackOverflowSlowPath : public SlowPathCode { |
| 481 public: |
| 482 explicit CheckStackOverflowSlowPath(CheckStackOverflowInstr* instruction) |
| 483 : instruction_(instruction) { } |
| 484 |
| 485 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
| 486 if (FLAG_use_osr) { |
| 487 uword flags_address = Isolate::Current()->stack_overflow_flags_address(); |
| 488 Register value = instruction_->locs()->temp(0).reg(); |
| 489 __ Comment("CheckStackOverflowSlowPathOsr"); |
| 490 __ Bind(osr_entry_label()); |
| 491 __ LoadImmediate(TMP, flags_address, PP); |
| 492 __ LoadImmediate(value, Isolate::kOsrRequest, PP); |
| 493 __ str(value, Address(TMP)); |
| 494 } |
| 495 __ Comment("CheckStackOverflowSlowPath"); |
| 496 __ Bind(entry_label()); |
| 497 compiler->SaveLiveRegisters(instruction_->locs()); |
| 498 // pending_deoptimization_env_ is needed to generate a runtime call that |
| 499 // may throw an exception. |
| 500 ASSERT(compiler->pending_deoptimization_env_ == NULL); |
| 501 Environment* env = compiler->SlowPathEnvironmentFor(instruction_); |
| 502 compiler->pending_deoptimization_env_ = env; |
| 503 compiler->GenerateRuntimeCall(instruction_->token_pos(), |
| 504 instruction_->deopt_id(), |
| 505 kStackOverflowRuntimeEntry, |
| 506 0, |
| 507 instruction_->locs()); |
| 508 |
| 509 if (FLAG_use_osr && !compiler->is_optimizing() && instruction_->in_loop()) { |
| 510 // In unoptimized code, record loop stack checks as possible OSR entries. |
| 511 compiler->AddCurrentDescriptor(PcDescriptors::kOsrEntry, |
| 512 instruction_->deopt_id(), |
| 513 0); // No token position. |
| 514 } |
| 515 compiler->pending_deoptimization_env_ = NULL; |
| 516 compiler->RestoreLiveRegisters(instruction_->locs()); |
| 517 __ b(exit_label()); |
| 518 } |
| 519 |
| 520 Label* osr_entry_label() { |
| 521 ASSERT(FLAG_use_osr); |
| 522 return &osr_entry_label_; |
| 523 } |
| 524 |
| 525 private: |
| 526 CheckStackOverflowInstr* instruction_; |
| 527 Label osr_entry_label_; |
| 528 }; |
| 529 |
| 530 |
| 442 void CheckStackOverflowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 531 void CheckStackOverflowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 443 UNIMPLEMENTED(); | 532 CheckStackOverflowSlowPath* slow_path = new CheckStackOverflowSlowPath(this); |
| 533 compiler->AddSlowPathCode(slow_path); |
| 534 |
| 535 __ LoadImmediate(TMP, Isolate::Current()->stack_limit_address(), PP); |
| 536 __ ldr(TMP, Address(TMP)); |
| 537 __ CompareRegisters(SP, TMP); |
| 538 __ b(slow_path->entry_label(), LS); |
| 539 if (compiler->CanOSRFunction() && in_loop()) { |
| 540 Register temp = locs()->temp(0).reg(); |
| 541 // In unoptimized code check the usage counter to trigger OSR at loop |
| 542 // stack checks. Use progressively higher thresholds for more deeply |
| 543 // nested loops to attempt to hit outer loops with OSR when possible. |
| 544 __ LoadObject(temp, compiler->parsed_function().function(), PP); |
| 545 intptr_t threshold = |
| 546 FLAG_optimization_counter_threshold * (loop_depth() + 1); |
| 547 __ LoadFieldFromOffset(temp, temp, Function::usage_counter_offset()); |
| 548 __ CompareImmediate(temp, threshold, PP); |
| 549 __ b(slow_path->osr_entry_label(), GE); |
| 550 } |
| 551 if (compiler->ForceSlowPathForStackOverflow()) { |
| 552 __ b(slow_path->entry_label()); |
| 553 } |
| 554 __ Bind(slow_path->exit_label()); |
| 444 } | 555 } |
| 445 | 556 |
| 446 | 557 |
| 447 LocationSummary* BinarySmiOpInstr::MakeLocationSummary(bool opt) const { | 558 LocationSummary* BinarySmiOpInstr::MakeLocationSummary(bool opt) const { |
| 448 UNIMPLEMENTED(); | 559 UNIMPLEMENTED(); |
| 449 return NULL; | 560 return NULL; |
| 450 } | 561 } |
| 451 | 562 |
| 452 | 563 |
| 453 void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 564 void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| (...skipping 716 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1170 return NULL; | 1281 return NULL; |
| 1171 } | 1282 } |
| 1172 | 1283 |
| 1173 | 1284 |
| 1174 void ReThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1285 void ReThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1175 UNIMPLEMENTED(); | 1286 UNIMPLEMENTED(); |
| 1176 } | 1287 } |
| 1177 | 1288 |
| 1178 | 1289 |
| 1179 void GraphEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1290 void GraphEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1180 UNIMPLEMENTED(); | 1291 if (!compiler->CanFallThroughTo(normal_entry())) { |
| 1292 __ b(compiler->GetJumpLabel(normal_entry())); |
| 1293 } |
| 1181 } | 1294 } |
| 1182 | 1295 |
| 1183 | 1296 |
| 1184 void TargetEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1297 void TargetEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1185 UNIMPLEMENTED(); | 1298 __ Bind(compiler->GetJumpLabel(this)); |
| 1299 if (!compiler->is_optimizing()) { |
| 1300 compiler->EmitEdgeCounter(); |
| 1301 // Add an edge counter. |
| 1302 // On ARM64 the deoptimization descriptor points after the edge counter |
| 1303 // code so that we can reuse the same pattern matching code as at call |
| 1304 // sites, which matches backwards from the end of the pattern. |
| 1305 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, |
| 1306 deopt_id_, |
| 1307 Scanner::kNoSourcePos); |
| 1308 } |
| 1309 if (HasParallelMove()) { |
| 1310 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); |
| 1311 } |
| 1186 } | 1312 } |
| 1187 | 1313 |
| 1188 | 1314 |
| 1189 LocationSummary* GotoInstr::MakeLocationSummary(bool opt) const { | 1315 LocationSummary* GotoInstr::MakeLocationSummary(bool opt) const { |
| 1190 UNIMPLEMENTED(); | 1316 UNIMPLEMENTED(); |
| 1191 return NULL; | 1317 return NULL; |
| 1192 } | 1318 } |
| 1193 | 1319 |
| 1194 | 1320 |
| 1195 void GotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1321 void GotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1249 } | 1375 } |
| 1250 | 1376 |
| 1251 | 1377 |
| 1252 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1378 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1253 UNIMPLEMENTED(); | 1379 UNIMPLEMENTED(); |
| 1254 } | 1380 } |
| 1255 | 1381 |
| 1256 } // namespace dart | 1382 } // namespace dart |
| 1257 | 1383 |
| 1258 #endif // defined TARGET_ARCH_ARM64 | 1384 #endif // defined TARGET_ARCH_ARM64 |
| OLD | NEW |