Chromium Code Reviews| Index: runtime/vm/flow_graph_compiler.cc |
| =================================================================== |
| --- runtime/vm/flow_graph_compiler.cc (revision 39726) |
| +++ runtime/vm/flow_graph_compiler.cc (working copy) |
| @@ -98,6 +98,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( |
| @@ -547,6 +548,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, |
| @@ -727,6 +729,8 @@ |
| Label* FlowGraphCompiler::AddDeoptStub(intptr_t deopt_id, |
| ICData::DeoptReasonId reason) { |
| + if (intrinsic_mode()) return &intrinsic_deopt_label_; |
|
srdjan
2014/09/02 18:48:21
This feels fragile as we must guaranteed that the
Florian Schneider
2014/09/02 21:03:20
Can you elaborate? There is only one instance of F
srdjan
2014/09/08 17:34:06
I was mainly worried that the lifetime of a FlowGr
|
| + |
| ASSERT(is_optimizing_); |
| CompilerDeoptInfoWithStub* stub = |
| new CompilerDeoptInfoWithStub(deopt_id, |
| @@ -855,9 +859,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. |
|
srdjan
2014/09/02 18:48:21
We do not deoptimize, this is actually the slow-pa
Florian Schneider
2014/09/02 21:03:20
That's why it's in quotes. Intrinsic code uses the
|
| + ASSERT(!intrinsic_deopt_label_.IsBound()); |
| + assembler()->Bind(&intrinsic_deopt_label_); |
| } |
| @@ -1290,13 +1300,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; |
| @@ -1306,7 +1320,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; |
| } |
| @@ -1326,7 +1340,7 @@ |
| spilled_(false) { |
| reg_ = static_cast<FpuRegister>( |
| resolver_->AllocateScratchRegister(Location::kFpuRegister, |
| - blocked, |
| + 1u << blocked, |
| 0, |
| kNumberOfFpuRegisters - 1, |
| &spilled_)); |
| @@ -1349,9 +1363,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_)); |