| Index: runtime/vm/intermediate_language_arm.cc
|
| diff --git a/runtime/vm/intermediate_language_arm.cc b/runtime/vm/intermediate_language_arm.cc
|
| index 13ad1238565f128cc5bdccb721024af9d4e0c645..84527e03218bb8cf74e3031480a35c1b0be8698b 100644
|
| --- a/runtime/vm/intermediate_language_arm.cc
|
| +++ b/runtime/vm/intermediate_language_arm.cc
|
| @@ -3050,6 +3050,91 @@ static void EmitSmiShiftLeft(FlowGraphCompiler* compiler,
|
| }
|
|
|
|
|
| +class CheckedSmiSlowPath : public SlowPathCode {
|
| + public:
|
| + CheckedSmiSlowPath(CheckedSmiOpInstr* instruction, intptr_t try_index)
|
| + : instruction_(instruction), try_index_(try_index) { }
|
| +
|
| + virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
|
| + if (Assembler::EmittingComments()) {
|
| + __ Comment("slow path smi operation");
|
| + }
|
| + __ Bind(entry_label());
|
| + LocationSummary* locs = instruction_->locs();
|
| + Register result = locs->out(0).reg();
|
| + locs->live_registers()->Remove(Location::RegisterLocation(result));
|
| +
|
| + compiler->SaveLiveRegisters(locs);
|
| + __ Push(locs->in(0).reg());
|
| + __ Push(locs->in(1).reg());
|
| + compiler->EmitMegamorphicInstanceCall(
|
| + *instruction_->call()->ic_data(),
|
| + instruction_->call()->ArgumentCount(),
|
| + instruction_->call()->deopt_id(),
|
| + instruction_->call()->token_pos(),
|
| + locs,
|
| + try_index_,
|
| + /* slow_path_argument_count = */ 2);
|
| + __ mov(result, Operand(R0));
|
| + compiler->RestoreLiveRegisters(locs);
|
| + __ b(exit_label());
|
| + }
|
| +
|
| + private:
|
| + CheckedSmiOpInstr* instruction_;
|
| + intptr_t try_index_;
|
| +};
|
| +
|
| +
|
| +LocationSummary* CheckedSmiOpInstr::MakeLocationSummary(Zone* zone,
|
| + bool opt) const {
|
| + const intptr_t kNumInputs = 2;
|
| + const intptr_t kNumTemps = 0;
|
| + LocationSummary* summary = new(zone) LocationSummary(
|
| + zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath);
|
| + summary->set_in(0, Location::RequiresRegister());
|
| + summary->set_in(1, Location::RequiresRegister());
|
| + summary->set_out(0, Location::RequiresRegister());
|
| + return summary;
|
| +}
|
| +
|
| +
|
| +void CheckedSmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
| + CheckedSmiSlowPath* slow_path =
|
| + new CheckedSmiSlowPath(this, compiler->CurrentTryIndex());
|
| + compiler->AddSlowPathCode(slow_path);
|
| + // Test operands if necessary.
|
| + Register left = locs()->in(0).reg();
|
| + Register right = locs()->in(1).reg();
|
| + Register result = locs()->out(0).reg();
|
| + __ orr(result, left, Operand(right));
|
| + __ tst(result, Operand(kSmiTagMask));
|
| + __ b(slow_path->entry_label(), NE);
|
| + switch (op_kind()) {
|
| + case Token::kADD:
|
| + __ adds(result, left, Operand(right));
|
| + __ b(slow_path->entry_label(), VS);
|
| + break;
|
| + case Token::kSUB:
|
| + __ subs(result, left, Operand(right));
|
| + __ b(slow_path->entry_label(), VS);
|
| + break;
|
| + case Token::kBIT_OR:
|
| + // Operation part of combined smi check.
|
| + break;
|
| + case Token::kBIT_AND:
|
| + __ and_(result, left, Operand(right));
|
| + break;
|
| + case Token::kBIT_XOR:
|
| + __ eor(result, left, Operand(right));
|
| + break;
|
| + default:
|
| + UNIMPLEMENTED();
|
| + }
|
| + __ Bind(slow_path->exit_label());
|
| +}
|
| +
|
| +
|
| LocationSummary* BinarySmiOpInstr::MakeLocationSummary(Zone* zone,
|
| bool opt) const {
|
| const intptr_t kNumInputs = 2;
|
|
|