| Index: runtime/vm/flow_graph_compiler.cc
|
| ===================================================================
|
| --- runtime/vm/flow_graph_compiler.cc (revision 39651)
|
| +++ runtime/vm/flow_graph_compiler.cc (working copy)
|
| @@ -92,6 +92,7 @@
|
| GrowableObjectArray::New())),
|
| is_optimizing_(is_optimizing),
|
| may_reoptimize_(false),
|
| + intrinsic_mode_(false),
|
| double_class_(Class::ZoneHandle(
|
| isolate_->object_store()->double_class())),
|
| mint_class_(Class::ZoneHandle(
|
| @@ -515,6 +516,7 @@
|
| void FlowGraphCompiler::AddDeoptIndexAtCall(intptr_t deopt_id,
|
| intptr_t token_pos) {
|
| ASSERT(is_optimizing());
|
| + ASSERT(!intrinsic_mode());
|
| CompilerDeoptInfo* info =
|
| new CompilerDeoptInfo(deopt_id,
|
| ICData::kDeoptAtCall,
|
| @@ -695,6 +697,8 @@
|
|
|
| Label* FlowGraphCompiler::AddDeoptStub(intptr_t deopt_id,
|
| ICData::DeoptReasonId reason) {
|
| + if (intrinsic_mode()) return &intrinsic_deopt_label_;
|
| +
|
| ASSERT(is_optimizing_);
|
| CompilerDeoptInfoWithStub* stub =
|
| new CompilerDeoptInfoWithStub(deopt_id,
|
| @@ -823,9 +827,15 @@
|
| }
|
| }
|
| }
|
| - // Even if an intrinsified version of the function was successfully
|
| - // generated, it may fall through to the non-intrinsified method body.
|
| - Intrinsifier::Intrinsify(parsed_function().function(), assembler());
|
| +
|
| + EnterIntrinsicMode();
|
| +
|
| + Intrinsifier::Intrinsify(parsed_function(), this);
|
| +
|
| + ExitIntrinsicMode();
|
| + // "Deoptimization" from intrinsic continues here.
|
| + ASSERT(!intrinsic_deopt_label_.IsBound());
|
| + assembler()->Bind(&intrinsic_deopt_label_);
|
| }
|
|
|
|
|
| @@ -1258,13 +1268,17 @@
|
|
|
| intptr_t ParallelMoveResolver::AllocateScratchRegister(
|
| Location::Kind kind,
|
| - intptr_t blocked,
|
| + uword blocked_mask,
|
| intptr_t first_free_register,
|
| intptr_t last_free_register,
|
| bool* spilled) {
|
| + COMPILE_ASSERT(static_cast<intptr_t>(sizeof(blocked_mask)) * kBitsPerByte >=
|
| + kNumberOfFpuRegisters);
|
| + COMPILE_ASSERT(static_cast<intptr_t>(sizeof(blocked_mask)) * kBitsPerByte >=
|
| + kNumberOfCpuRegisters);
|
| intptr_t scratch = -1;
|
| for (intptr_t reg = first_free_register; reg <= last_free_register; reg++) {
|
| - if ((blocked != reg) &&
|
| + if ((((1u << reg) & blocked_mask) == 0) &&
|
| IsScratchLocation(Location::MachineRegisterLocation(kind, reg))) {
|
| scratch = reg;
|
| break;
|
| @@ -1274,7 +1288,7 @@
|
| if (scratch == -1) {
|
| *spilled = true;
|
| for (intptr_t reg = first_free_register; reg <= last_free_register; reg++) {
|
| - if (blocked != reg) {
|
| + if (((1u << reg) & blocked_mask) == 0) {
|
| scratch = reg;
|
| break;
|
| }
|
| @@ -1294,7 +1308,7 @@
|
| spilled_(false) {
|
| reg_ = static_cast<FpuRegister>(
|
| resolver_->AllocateScratchRegister(Location::kFpuRegister,
|
| - blocked,
|
| + 1u << blocked,
|
| 0,
|
| kNumberOfFpuRegisters - 1,
|
| &spilled_));
|
| @@ -1317,9 +1331,15 @@
|
| : resolver_(resolver),
|
| reg_(kNoRegister),
|
| spilled_(false) {
|
| + uword blocked_mask = 1u << blocked;
|
| + if (resolver->compiler_->intrinsic_mode()) {
|
| + // Block additional registers that must be preserved for intrinsics.
|
| + blocked_mask |= 1u << ICREG;
|
| + blocked_mask |= 1u << ARGS_DESC_REG;
|
| + }
|
| reg_ = static_cast<Register>(
|
| resolver_->AllocateScratchRegister(Location::kRegister,
|
| - blocked,
|
| + 1u << blocked,
|
| kFirstFreeCpuRegister,
|
| kLastFreeCpuRegister,
|
| &spilled_));
|
|
|