| Index: runtime/vm/intermediate_language_arm.cc
|
| diff --git a/runtime/vm/intermediate_language_arm.cc b/runtime/vm/intermediate_language_arm.cc
|
| index 1750418cc79f0c55bb2670917336dea52c345fac..ffe6f7f8fb3f9cc482eaa05302c6e3c42a820af4 100644
|
| --- a/runtime/vm/intermediate_language_arm.cc
|
| +++ b/runtime/vm/intermediate_language_arm.cc
|
| @@ -6135,6 +6135,71 @@ void CheckClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
| }
|
|
|
|
|
| +LocationSummary* GenericCheckBoundInstr::MakeLocationSummary(Zone* zone,
|
| + bool opt) const {
|
| + const intptr_t kNumInputs = 2;
|
| + const intptr_t kNumTemps = 0;
|
| + LocationSummary* locs = new(zone) LocationSummary(
|
| + zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath);
|
| + locs->set_in(kLengthPos, Location::RequiresRegister());
|
| + locs->set_in(kIndexPos, Location::RequiresRegister());
|
| + return locs;
|
| +}
|
| +
|
| +
|
| +class RangeErrorSlowPath : public SlowPathCode {
|
| + public:
|
| + RangeErrorSlowPath(GenericCheckBoundInstr* instruction, intptr_t try_index)
|
| + : instruction_(instruction), try_index_(try_index) { }
|
| +
|
| + virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
|
| + if (Assembler::EmittingComments()) {
|
| + __ Comment("slow path check bound operation");
|
| + }
|
| + __ Bind(entry_label());
|
| + LocationSummary* locs = instruction_->locs();
|
| + __ Push(locs->in(0).reg());
|
| + __ Push(locs->in(1).reg());
|
| + compiler->GenerateRuntimeCall(instruction_->token_pos(),
|
| + instruction_->deopt_id(),
|
| + kRangeErrorRuntimeEntry,
|
| + 2,
|
| + instruction_->locs());
|
| + compiler->RecordSafepoint(locs, /* slow_path_argument_count = */ 2);
|
| + compiler->pc_descriptors_list()->AddDescriptor(
|
| + RawPcDescriptors::kOther,
|
| + compiler->assembler()->CodeSize(),
|
| + instruction_->deopt_id(),
|
| + instruction_->token_pos(),
|
| + try_index_);
|
| + __ bkpt(0);
|
| + }
|
| +
|
| + private:
|
| + GenericCheckBoundInstr* instruction_;
|
| + intptr_t try_index_;
|
| +};
|
| +
|
| +
|
| +void GenericCheckBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
| + RangeErrorSlowPath* slow_path =
|
| + new RangeErrorSlowPath(this, compiler->CurrentTryIndex());
|
| + compiler->AddSlowPathCode(slow_path);
|
| +
|
| + Location length_loc = locs()->in(kLengthPos);
|
| + Location index_loc = locs()->in(kIndexPos);
|
| + Register length = length_loc.reg();
|
| + Register index = index_loc.reg();
|
| + const intptr_t index_cid = this->index()->Type()->ToCid();
|
| + if (index_cid != kSmiCid) {
|
| + __ tst(index, Operand(kSmiTagMask));
|
| + __ b(slow_path->entry_label(), NE);
|
| + }
|
| + __ cmp(index, Operand(length));
|
| + __ b(slow_path->entry_label(), CS);
|
| +}
|
| +
|
| +
|
| LocationSummary* CheckArrayBoundInstr::MakeLocationSummary(Zone* zone,
|
| bool opt) const {
|
| const intptr_t kNumInputs = 2;
|
| @@ -6168,6 +6233,7 @@ void CheckArrayBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
| return;
|
| }
|
|
|
| + const intptr_t index_cid = index()->Type()->ToCid();
|
| if (index_loc.IsConstant()) {
|
| const Register length = length_loc.reg();
|
| const Smi& index = Smi::Cast(index_loc.constant());
|
| @@ -6176,6 +6242,10 @@ void CheckArrayBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
| } else if (length_loc.IsConstant()) {
|
| const Smi& length = Smi::Cast(length_loc.constant());
|
| const Register index = index_loc.reg();
|
| + if (index_cid != kSmiCid) {
|
| + __ tst(index, Operand(kSmiTagMask));
|
| + __ b(deopt, NE);
|
| + }
|
| if (length.Value() == Smi::kMaxValue) {
|
| __ tst(index, Operand(index));
|
| __ b(deopt, MI);
|
| @@ -6186,6 +6256,10 @@ void CheckArrayBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
| } else {
|
| const Register length = length_loc.reg();
|
| const Register index = index_loc.reg();
|
| + if (index_cid != kSmiCid) {
|
| + __ tst(index, Operand(kSmiTagMask));
|
| + __ b(deopt, NE);
|
| + }
|
| __ cmp(index, Operand(length));
|
| __ b(deopt, CS);
|
| }
|
|
|