| Index: runtime/vm/intermediate_language_x64.cc
|
| ===================================================================
|
| --- runtime/vm/intermediate_language_x64.cc (revision 17135)
|
| +++ runtime/vm/intermediate_language_x64.cc (working copy)
|
| @@ -936,6 +936,9 @@
|
| LocationSummary* locs =
|
| new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
|
| locs->set_in(0, Location::RequiresRegister());
|
| + // The smi index is either untagged and tagged again at the end of the
|
| + // operation (element size == 1), or it is left smi tagged (for all element
|
| + // sizes > 1).
|
| locs->set_in(1, CanBeImmediateIndex(index(), class_id())
|
| ? Location::RegisterOrSmiConstant(index())
|
| : Location::RequiresRegister());
|
| @@ -1005,6 +1008,9 @@
|
| LocationSummary* locs =
|
| new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
|
| locs->set_in(0, Location::RequiresRegister());
|
| + // The smi index is either untagged and tagged again at the end of the
|
| + // operation (element size == 1), or it is left smi tagged (for all element
|
| + // sizes > 1).
|
| locs->set_in(1, CanBeImmediateIndex(index(), class_id())
|
| ? Location::RegisterOrSmiConstant(index())
|
| : Location::RequiresRegister());
|
| @@ -1024,8 +1030,10 @@
|
| if (class_id() == kExternalUint8ArrayCid) {
|
| Register result = locs()->out().reg();
|
| Address element_address = index.IsRegister()
|
| - ? Address(result, index.reg(), TIMES_1, 0)
|
| - : Address(result, Smi::Cast(index.constant()).Value());
|
| + ? FlowGraphCompiler::ExternalElementAddressForRegIndex(
|
| + class_id(), result, index.reg())
|
| + : FlowGraphCompiler::ExternalElementAddressForIntIndex(
|
| + class_id(), result, Smi::Cast(index.constant()).Value());
|
| if (index.IsRegister()) {
|
| __ SmiUntag(index.reg());
|
| }
|
| @@ -1062,29 +1070,47 @@
|
| }
|
|
|
| Register result = locs()->out().reg();
|
| - if ((class_id() == kUint8ArrayCid) ||
|
| - (class_id() == kUint8ClampedArrayCid)) {
|
| - if (index.IsRegister()) {
|
| - __ SmiUntag(index.reg());
|
| - }
|
| - __ movzxb(result, element_address);
|
| - __ SmiTag(result);
|
| - if (index.IsRegister()) {
|
| - __ SmiTag(index.reg()); // Re-tag.
|
| - }
|
| - return;
|
| + switch (class_id()) {
|
| + case kInt8ArrayCid:
|
| + case kUint8ArrayCid:
|
| + case kUint8ClampedArrayCid:
|
| + if (index.IsRegister()) {
|
| + __ SmiUntag(index.reg());
|
| + }
|
| + if (class_id() == kInt8ArrayCid) {
|
| + __ movsxb(result, element_address);
|
| + } else {
|
| + __ movzxb(result, element_address);
|
| + }
|
| + __ SmiTag(result);
|
| + if (index.IsRegister()) {
|
| + __ SmiTag(index.reg()); // Re-tag.
|
| + }
|
| + break;
|
| + case kInt16ArrayCid:
|
| + __ movsxw(result, element_address);
|
| + __ SmiTag(result);
|
| + break;
|
| + case kUint16ArrayCid:
|
| + __ movzxw(result, element_address);
|
| + __ SmiTag(result);
|
| + break;
|
| + default:
|
| + ASSERT((class_id() == kArrayCid) || (class_id() == kImmutableArrayCid));
|
| + __ movq(result, element_address);
|
| + break;
|
| }
|
| -
|
| - ASSERT((class_id() == kArrayCid) || (class_id() == kImmutableArrayCid));
|
| - __ movq(result, element_address);
|
| }
|
|
|
|
|
| LocationSummary* StoreIndexedInstr::MakeLocationSummary() const {
|
| const intptr_t kNumInputs = 3;
|
| - const intptr_t numTemps = 0;
|
| + const intptr_t kNumTemps = 0;
|
| LocationSummary* locs =
|
| - new LocationSummary(kNumInputs, numTemps, LocationSummary::kNoCall);
|
| + new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
|
| + // The smi index is either untagged and tagged again at the end of the
|
| + // operation (element size == 1), or it is left smi tagged (for all element
|
| + // sizes > 1).
|
| locs->set_in(0, Location::RequiresRegister());
|
| locs->set_in(1, CanBeImmediateIndex(index(), class_id())
|
| ? Location::RegisterOrSmiConstant(index())
|
| @@ -1095,11 +1121,18 @@
|
| ? Location::WritableRegister()
|
| : Location::RegisterOrConstant(value()));
|
| break;
|
| + case kInt8ArrayCid:
|
| case kUint8ArrayCid:
|
| + case kUint8ClampedArrayCid:
|
| // TODO(fschneider): Add location constraint for byte registers (RAX,
|
| // RBX, RCX, RDX) instead of using a fixed register.
|
| locs->set_in(2, Location::FixedRegisterOrSmiConstant(value(), RAX));
|
| break;
|
| + case kInt16ArrayCid:
|
| + case kUint16ArrayCid:
|
| + // Writable register because the value must be untagged before storing.
|
| + locs->set_in(2, Location::WritableRegister());
|
| + break;
|
| case kFloat32ArrayCid:
|
| // Need temp register for float-to-double conversion.
|
| locs->AddTemp(Location::RequiresXmmRegister());
|
| @@ -1139,6 +1172,7 @@
|
| __ StoreIntoObjectNoBarrier(array, element_address, value);
|
| }
|
| break;
|
| + case kInt8ArrayCid:
|
| case kUint8ArrayCid:
|
| if (index.IsRegister()) {
|
| __ SmiUntag(index.reg());
|
| @@ -1156,6 +1190,48 @@
|
| __ SmiTag(index.reg()); // Re-tag.
|
| }
|
| break;
|
| + case kUint8ClampedArrayCid: {
|
| + if (index.IsRegister()) {
|
| + __ SmiUntag(index.reg());
|
| + }
|
| + if (locs()->in(2).IsConstant()) {
|
| + const Smi& constant = Smi::Cast(locs()->in(2).constant());
|
| + intptr_t value = constant.Value();
|
| + // Clamp to 0x0 or 0xFF respectively.
|
| + if (value > 0xFF) {
|
| + value = 0xFF;
|
| + } else if (value < 0) {
|
| + value = 0;
|
| + }
|
| + __ movb(element_address,
|
| + Immediate(static_cast<int8_t>(value)));
|
| + } else {
|
| + ASSERT(locs()->in(2).reg() == RAX);
|
| + Label store_value, store_0xff;
|
| + __ SmiUntag(RAX);
|
| + __ cmpq(RAX, Immediate(0xFF));
|
| + __ j(BELOW_EQUAL, &store_value, Assembler::kNearJump);
|
| + // Clamp to 0x0 or 0xFF respectively.
|
| + __ j(GREATER, &store_0xff);
|
| + __ xorq(RAX, RAX);
|
| + __ jmp(&store_value, Assembler::kNearJump);
|
| + __ Bind(&store_0xff);
|
| + __ movq(RAX, Immediate(0xFF));
|
| + __ Bind(&store_value);
|
| + __ movb(element_address, RAX);
|
| + }
|
| + if (index.IsRegister()) {
|
| + __ SmiTag(index.reg()); // Re-tag.
|
| + }
|
| + break;
|
| + }
|
| + case kInt16ArrayCid:
|
| + case kUint16ArrayCid: {
|
| + Register value = locs()->in(2).reg();
|
| + __ SmiUntag(value);
|
| + __ movw(element_address, value);
|
| + break;
|
| + }
|
| case kFloat32ArrayCid:
|
| // Convert to single precision.
|
| __ cvtsd2ss(locs()->temp(0).xmm_reg(), locs()->in(2).xmm_reg());
|
|
|