Chromium Code Reviews| Index: runtime/vm/intermediate_language_ia32.cc |
| =================================================================== |
| --- runtime/vm/intermediate_language_ia32.cc (revision 14406) |
| +++ runtime/vm/intermediate_language_ia32.cc (working copy) |
| @@ -1086,6 +1086,45 @@ |
| } |
| +LocationSummary* StringCharCodeAtInstr::MakeLocationSummary() const { |
| + const intptr_t kNumInputs = 2; |
| + const intptr_t kNumTemps = 0; |
| + LocationSummary* locs = |
| + new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| + locs->set_in(0, Location::RequiresRegister()); |
| + // TODO(fschneider): Allow immediate operands for the index. |
| + locs->set_in(1, Location::RequiresRegister()); |
| + locs->set_out(Location::RequiresRegister()); |
| + return locs; |
| +} |
| + |
| + |
| +void StringCharCodeAtInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| + Register str = locs()->in(0).reg(); |
| + Register index = locs()->in(1).reg(); |
| + Register result = locs()->out().reg(); |
| + |
| + ASSERT((class_id() == kOneByteStringCid) || |
| + (class_id() == kTwoByteStringCid)); |
| + if (class_id() == kOneByteStringCid) { |
| + __ SmiUntag(index); |
|
srdjan
2012/11/01 20:32:18
Is it better to tag/untag or to require a temporar
Florian Schneider
2012/11/01 22:58:56
With a quick test, I found no noticable difference
|
| + __ movzxb(result, FieldAddress(str, |
| + index, |
| + TIMES_1, |
| + OneByteString::data_offset())); |
| + __ SmiTag(index); // Retag index. |
| + __ SmiTag(result); |
| + } else { |
| + // Don't untag smi-index and use TIMES_1 for two byte strings. |
| + __ movzxw(result, FieldAddress(str, |
| + index, |
| + TIMES_1, |
| + TwoByteString::data_offset())); |
| + __ SmiTag(result); |
| + } |
| +} |
| + |
| + |
| LocationSummary* LoadIndexedInstr::MakeLocationSummary() const { |
| const intptr_t kNumInputs = 2; |
| const intptr_t kNumTemps = 0; |
| @@ -2354,29 +2393,16 @@ |
| void CheckArrayBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| - const DeoptReasonId deopt_reason = |
| - (array_type() == kGrowableObjectArrayCid) ? |
| - kDeoptLoadIndexedGrowableArray : kDeoptLoadIndexedFixedArray; |
| Label* deopt = compiler->AddDeoptStub(deopt_id(), |
| - deopt_reason); |
| - ASSERT((array_type() == kArrayCid) || |
| - (array_type() == kImmutableArrayCid) || |
| - (array_type() == kGrowableObjectArrayCid) || |
| - (array_type() == kFloat64ArrayCid) || |
| - (array_type() == kFloat32ArrayCid)); |
| - intptr_t length_offset = -1; |
| - if (array_type() == kGrowableObjectArrayCid) { |
| - length_offset = GrowableObjectArray::length_offset(); |
| - } else if (array_type() == kFloat64ArrayCid) { |
| - length_offset = Float64Array::length_offset(); |
| - } else if (array_type() == kFloat32ArrayCid) { |
| - length_offset = Float32Array::length_offset(); |
| - } else { |
| - length_offset = Array::length_offset(); |
| + kDeoptCheckArrayBound); |
| + if (locs()->in(0).IsConstant() && locs()->in(1).IsConstant()) { |
| + // Unconditionally deoptimize for constant bounds checks because they |
| + // only occur only when index is out-of-bounds. |
| + __ jmp(deopt); |
| + return; |
| } |
| - // This case should not have created a bound check instruction. |
| - ASSERT(!(locs()->in(0).IsConstant() && locs()->in(1).IsConstant())); |
| + intptr_t length_offset = LengthOffsetFor(array_type()); |
| if (locs()->in(1).IsConstant()) { |
| Register receiver = locs()->in(0).reg(); |
| const Object& constant = locs()->in(1).constant(); |
| @@ -2386,12 +2412,14 @@ |
| __ cmpl(FieldAddress(receiver, length_offset), Immediate(imm)); |
| __ j(BELOW_EQUAL, deopt); |
| } else if (locs()->in(0).IsConstant()) { |
| - const Object& constant = locs()->in(0).constant(); |
| - ASSERT(constant.IsArray()); |
| - const Array& array = Array::Cast(constant); |
| + ASSERT(locs()->in(0).constant().IsArray() || |
| + locs()->in(0).constant().IsString()); |
| + intptr_t length = locs()->in(0).constant().IsArray() |
| + ? Array::Cast(locs()->in(0).constant()).Length() |
| + : String::Cast(locs()->in(0).constant()).Length(); |
| Register index = locs()->in(1).reg(); |
| __ cmpl(index, |
| - Immediate(reinterpret_cast<int32_t>(Smi::New(array.Length())))); |
| + Immediate(reinterpret_cast<int32_t>(Smi::New(length)))); |
| __ j(ABOVE_EQUAL, deopt); |
| } else { |
| Register receiver = locs()->in(0).reg(); |