mirror of
https://github.com/dart-lang/sdk
synced 2024-09-20 02:17:58 +00:00
Last cross-platform cleanup in preparation of improved ARM code for indexed
loads and stores. R=srdjan@google.com Review URL: https://codereview.chromium.org//294223003 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@36577 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
parent
c6101ca4b5
commit
9868b7ed94
|
@ -2197,7 +2197,7 @@ void EffectGraphVisitor::VisitArrayNode(ArrayNode* node) {
|
|||
for_value.value()->BindsToConstant()
|
||||
? kNoStoreBarrier
|
||||
: kEmitStoreBarrier;
|
||||
intptr_t index_scale = FlowGraphCompiler::ElementSizeFor(class_id);
|
||||
const intptr_t index_scale = Instance::ElementSizeFor(class_id);
|
||||
StoreIndexedInstr* store = new StoreIndexedInstr(
|
||||
array, index, for_value.value(), emit_store_barrier,
|
||||
index_scale, class_id, deopt_id, node->token_pos());
|
||||
|
|
|
@ -1289,50 +1289,6 @@ ParallelMoveResolver::ScratchRegisterScope::~ScratchRegisterScope() {
|
|||
}
|
||||
|
||||
|
||||
intptr_t FlowGraphCompiler::ElementSizeFor(intptr_t cid) {
|
||||
if (RawObject::IsExternalTypedDataClassId(cid)) {
|
||||
return ExternalTypedData::ElementSizeInBytes(cid);
|
||||
} else if (RawObject::IsTypedDataClassId(cid)) {
|
||||
return TypedData::ElementSizeInBytes(cid);
|
||||
}
|
||||
switch (cid) {
|
||||
case kArrayCid:
|
||||
case kImmutableArrayCid:
|
||||
return Array::kBytesPerElement;
|
||||
case kOneByteStringCid:
|
||||
return OneByteString::kBytesPerElement;
|
||||
case kTwoByteStringCid:
|
||||
return TwoByteString::kBytesPerElement;
|
||||
default:
|
||||
UNIMPLEMENTED();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
intptr_t FlowGraphCompiler::DataOffsetFor(intptr_t cid) {
|
||||
if (RawObject::IsExternalTypedDataClassId(cid)) {
|
||||
// Elements start at offset 0 of the external data.
|
||||
return 0;
|
||||
}
|
||||
if (RawObject::IsTypedDataClassId(cid)) {
|
||||
return TypedData::data_offset();
|
||||
}
|
||||
switch (cid) {
|
||||
case kArrayCid:
|
||||
case kImmutableArrayCid:
|
||||
return Array::data_offset();
|
||||
case kOneByteStringCid:
|
||||
return OneByteString::data_offset();
|
||||
case kTwoByteStringCid:
|
||||
return TwoByteString::data_offset();
|
||||
default:
|
||||
UNIMPLEMENTED();
|
||||
return Array::data_offset();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int HighestCountFirst(const CidTarget* a, const CidTarget* b) {
|
||||
// Negative if 'a' should sort before 'b'.
|
||||
return b->count - a->count;
|
||||
|
|
|
@ -447,24 +447,6 @@ class FlowGraphCompiler : public ValueObject {
|
|||
|
||||
bool may_reoptimize() const { return may_reoptimize_; }
|
||||
|
||||
// Array/list element address computations.
|
||||
static intptr_t DataOffsetFor(intptr_t cid);
|
||||
static intptr_t ElementSizeFor(intptr_t cid);
|
||||
Address ElementAddressForIntIndex(intptr_t cid,
|
||||
intptr_t index_scale,
|
||||
Register array,
|
||||
intptr_t offset);
|
||||
Address ElementAddressForRegIndex(intptr_t cid,
|
||||
intptr_t index_scale,
|
||||
Register array,
|
||||
Register index);
|
||||
Address ExternalElementAddressForIntIndex(intptr_t index_scale,
|
||||
Register array,
|
||||
intptr_t offset);
|
||||
Address ExternalElementAddressForRegIndex(intptr_t index_scale,
|
||||
Register array,
|
||||
Register index);
|
||||
|
||||
// Returns 'sorted' array in decreasing count order.
|
||||
static void SortICDataByCount(const ICData& ic_data,
|
||||
GrowableArray<CidTarget>* sorted);
|
||||
|
|
|
@ -1511,11 +1511,11 @@ void FlowGraphCompiler::EmitTestAndCall(const ICData& ic_data,
|
|||
for (intptr_t i = 0; i < len; i++) {
|
||||
const bool is_last_check = (i == (len - 1));
|
||||
Label next_test;
|
||||
assembler()->CompareImmediate(class_id_reg, sorted[i].cid);
|
||||
__ CompareImmediate(class_id_reg, sorted[i].cid);
|
||||
if (is_last_check) {
|
||||
assembler()->b(deopt, NE);
|
||||
__ b(deopt, NE);
|
||||
} else {
|
||||
assembler()->b(&next_test, NE);
|
||||
__ b(&next_test, NE);
|
||||
}
|
||||
// Do not use the code from the function, but let the code be patched so
|
||||
// that we can record the outgoing edges to other code.
|
||||
|
@ -1528,47 +1528,11 @@ void FlowGraphCompiler::EmitTestAndCall(const ICData& ic_data,
|
|||
AddStaticCallTarget(function);
|
||||
__ Drop(argument_count);
|
||||
if (!is_last_check) {
|
||||
assembler()->b(&match_found);
|
||||
__ b(&match_found);
|
||||
}
|
||||
assembler()->Bind(&next_test);
|
||||
__ Bind(&next_test);
|
||||
}
|
||||
assembler()->Bind(&match_found);
|
||||
}
|
||||
|
||||
|
||||
Address FlowGraphCompiler::ElementAddressForIntIndex(intptr_t cid,
|
||||
intptr_t index_scale,
|
||||
Register array,
|
||||
intptr_t index) {
|
||||
UNREACHABLE();
|
||||
return FieldAddress(array, index);
|
||||
}
|
||||
|
||||
|
||||
Address FlowGraphCompiler::ElementAddressForRegIndex(intptr_t cid,
|
||||
intptr_t index_scale,
|
||||
Register array,
|
||||
Register index) {
|
||||
UNREACHABLE();
|
||||
return FieldAddress(array, index);
|
||||
}
|
||||
|
||||
|
||||
Address FlowGraphCompiler::ExternalElementAddressForIntIndex(
|
||||
intptr_t index_scale,
|
||||
Register array,
|
||||
intptr_t index) {
|
||||
UNREACHABLE();
|
||||
return FieldAddress(array, index);
|
||||
}
|
||||
|
||||
|
||||
Address FlowGraphCompiler::ExternalElementAddressForRegIndex(
|
||||
intptr_t index_scale,
|
||||
Register array,
|
||||
Register index) {
|
||||
UNREACHABLE();
|
||||
return FieldAddress(array, index);
|
||||
__ Bind(&match_found);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1529,42 +1529,6 @@ void FlowGraphCompiler::EmitTestAndCall(const ICData& ic_data,
|
|||
}
|
||||
|
||||
|
||||
Address FlowGraphCompiler::ElementAddressForIntIndex(intptr_t cid,
|
||||
intptr_t index_scale,
|
||||
Register array,
|
||||
intptr_t index) {
|
||||
UNREACHABLE();
|
||||
return FieldAddress(array, index);
|
||||
}
|
||||
|
||||
|
||||
Address FlowGraphCompiler::ElementAddressForRegIndex(intptr_t cid,
|
||||
intptr_t index_scale,
|
||||
Register array,
|
||||
Register index) {
|
||||
UNREACHABLE();
|
||||
return FieldAddress(array, index);
|
||||
}
|
||||
|
||||
|
||||
Address FlowGraphCompiler::ExternalElementAddressForIntIndex(
|
||||
intptr_t index_scale,
|
||||
Register array,
|
||||
intptr_t index) {
|
||||
UNREACHABLE();
|
||||
return FieldAddress(array, index);
|
||||
}
|
||||
|
||||
|
||||
Address FlowGraphCompiler::ExternalElementAddressForRegIndex(
|
||||
intptr_t index_scale,
|
||||
Register array,
|
||||
Register index) {
|
||||
UNREACHABLE();
|
||||
return FieldAddress(array, index);
|
||||
}
|
||||
|
||||
|
||||
#undef __
|
||||
#define __ compiler_->assembler()->
|
||||
|
||||
|
|
|
@ -1539,62 +1539,6 @@ void FlowGraphCompiler::EmitTestAndCall(const ICData& ic_data,
|
|||
}
|
||||
|
||||
|
||||
Address FlowGraphCompiler::ElementAddressForIntIndex(intptr_t cid,
|
||||
intptr_t index_scale,
|
||||
Register array,
|
||||
intptr_t index) {
|
||||
const int64_t disp =
|
||||
static_cast<int64_t>(index) * index_scale + DataOffsetFor(cid);
|
||||
ASSERT(Utils::IsInt(32, disp));
|
||||
return FieldAddress(array, static_cast<int32_t>(disp));
|
||||
}
|
||||
|
||||
|
||||
static ScaleFactor ToScaleFactor(intptr_t index_scale) {
|
||||
// Note that index is expected smi-tagged, (i.e, times 2) for all arrays with
|
||||
// index scale factor > 1. E.g., for Uint8Array and OneByteString the index is
|
||||
// expected to be untagged before accessing.
|
||||
ASSERT(kSmiTagShift == 1);
|
||||
switch (index_scale) {
|
||||
case 1: return TIMES_1;
|
||||
case 2: return TIMES_1;
|
||||
case 4: return TIMES_2;
|
||||
case 8: return TIMES_4;
|
||||
case 16: return TIMES_8;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return TIMES_1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Address FlowGraphCompiler::ElementAddressForRegIndex(intptr_t cid,
|
||||
intptr_t index_scale,
|
||||
Register array,
|
||||
Register index) {
|
||||
return FieldAddress(array,
|
||||
index,
|
||||
ToScaleFactor(index_scale),
|
||||
DataOffsetFor(cid));
|
||||
}
|
||||
|
||||
|
||||
Address FlowGraphCompiler::ExternalElementAddressForIntIndex(
|
||||
intptr_t index_scale,
|
||||
Register array,
|
||||
intptr_t index) {
|
||||
return Address(array, index * index_scale);
|
||||
}
|
||||
|
||||
|
||||
Address FlowGraphCompiler::ExternalElementAddressForRegIndex(
|
||||
intptr_t index_scale,
|
||||
Register array,
|
||||
Register index) {
|
||||
return Address(array, index, ToScaleFactor(index_scale), 0);
|
||||
}
|
||||
|
||||
|
||||
#undef __
|
||||
#define __ compiler_->assembler()->
|
||||
|
||||
|
|
|
@ -1597,42 +1597,6 @@ void FlowGraphCompiler::EmitTestAndCall(const ICData& ic_data,
|
|||
}
|
||||
|
||||
|
||||
Address FlowGraphCompiler::ElementAddressForIntIndex(intptr_t cid,
|
||||
intptr_t index_scale,
|
||||
Register array,
|
||||
intptr_t index) {
|
||||
UNREACHABLE();
|
||||
return FieldAddress(array, index);
|
||||
}
|
||||
|
||||
|
||||
Address FlowGraphCompiler::ElementAddressForRegIndex(intptr_t cid,
|
||||
intptr_t index_scale,
|
||||
Register array,
|
||||
Register index) {
|
||||
UNREACHABLE();
|
||||
return FieldAddress(array, index);
|
||||
}
|
||||
|
||||
|
||||
Address FlowGraphCompiler::ExternalElementAddressForIntIndex(
|
||||
intptr_t index_scale,
|
||||
Register array,
|
||||
intptr_t index) {
|
||||
UNREACHABLE();
|
||||
return FieldAddress(array, index);
|
||||
}
|
||||
|
||||
|
||||
Address FlowGraphCompiler::ExternalElementAddressForRegIndex(
|
||||
intptr_t index_scale,
|
||||
Register array,
|
||||
Register index) {
|
||||
UNREACHABLE();
|
||||
return FieldAddress(array, index);
|
||||
}
|
||||
|
||||
|
||||
#undef __
|
||||
#define __ compiler_->assembler()->
|
||||
|
||||
|
|
|
@ -1550,11 +1550,11 @@ void FlowGraphCompiler::EmitTestAndCall(const ICData& ic_data,
|
|||
for (intptr_t i = 0; i < len; i++) {
|
||||
const bool is_last_check = (i == (len - 1));
|
||||
Label next_test;
|
||||
assembler()->cmpl(class_id_reg, Immediate(sorted[i].cid));
|
||||
__ cmpl(class_id_reg, Immediate(sorted[i].cid));
|
||||
if (is_last_check) {
|
||||
assembler()->j(NOT_EQUAL, deopt);
|
||||
__ j(NOT_EQUAL, deopt);
|
||||
} else {
|
||||
assembler()->j(NOT_EQUAL, &next_test);
|
||||
__ j(NOT_EQUAL, &next_test);
|
||||
}
|
||||
// Do not use the code from the function, but let the code be patched so
|
||||
// that we can record the outgoing edges to other code.
|
||||
|
@ -1567,67 +1567,11 @@ void FlowGraphCompiler::EmitTestAndCall(const ICData& ic_data,
|
|||
AddStaticCallTarget(function);
|
||||
__ Drop(argument_count);
|
||||
if (!is_last_check) {
|
||||
assembler()->jmp(&match_found);
|
||||
__ jmp(&match_found);
|
||||
}
|
||||
assembler()->Bind(&next_test);
|
||||
__ Bind(&next_test);
|
||||
}
|
||||
assembler()->Bind(&match_found);
|
||||
}
|
||||
|
||||
|
||||
Address FlowGraphCompiler::ElementAddressForIntIndex(intptr_t cid,
|
||||
intptr_t index_scale,
|
||||
Register array,
|
||||
intptr_t index) {
|
||||
const int64_t disp =
|
||||
static_cast<int64_t>(index) * index_scale + DataOffsetFor(cid);
|
||||
ASSERT(Utils::IsInt(32, disp));
|
||||
return FieldAddress(array, static_cast<int32_t>(disp));
|
||||
}
|
||||
|
||||
|
||||
static ScaleFactor ToScaleFactor(intptr_t index_scale) {
|
||||
// Note that index is expected smi-tagged, (i.e, times 2) for all arrays with
|
||||
// index scale factor > 1. E.g., for Uint8Array and OneByteString the index is
|
||||
// expected to be untagged before accessing.
|
||||
ASSERT(kSmiTagShift == 1);
|
||||
switch (index_scale) {
|
||||
case 1: return TIMES_1;
|
||||
case 2: return TIMES_1;
|
||||
case 4: return TIMES_2;
|
||||
case 8: return TIMES_4;
|
||||
case 16: return TIMES_8;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return TIMES_1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Address FlowGraphCompiler::ElementAddressForRegIndex(intptr_t cid,
|
||||
intptr_t index_scale,
|
||||
Register array,
|
||||
Register index) {
|
||||
return FieldAddress(array,
|
||||
index,
|
||||
ToScaleFactor(index_scale),
|
||||
DataOffsetFor(cid));
|
||||
}
|
||||
|
||||
|
||||
Address FlowGraphCompiler::ExternalElementAddressForIntIndex(
|
||||
intptr_t index_scale,
|
||||
Register array,
|
||||
intptr_t index) {
|
||||
return Address(array, index * index_scale);
|
||||
}
|
||||
|
||||
|
||||
Address FlowGraphCompiler::ExternalElementAddressForRegIndex(
|
||||
intptr_t index_scale,
|
||||
Register array,
|
||||
Register index) {
|
||||
return Address(array, index, ToScaleFactor(index_scale), 0);
|
||||
__ Bind(&match_found);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -311,7 +311,7 @@ void FlowGraphOptimizer::OptimizeLeftShiftBitAndSmiOp(
|
|||
void FlowGraphOptimizer::AppendLoadIndexedForMerged(Definition* instr,
|
||||
intptr_t ix,
|
||||
intptr_t cid) {
|
||||
const intptr_t index_scale = FlowGraphCompiler::ElementSizeFor(cid);
|
||||
const intptr_t index_scale = Instance::ElementSizeFor(cid);
|
||||
ConstantInstr* index_instr =
|
||||
flow_graph()->GetConstant(Smi::Handle(Smi::New(ix)));
|
||||
LoadIndexedInstr* load = new LoadIndexedInstr(new Value(instr),
|
||||
|
@ -1301,7 +1301,7 @@ bool FlowGraphOptimizer::InlineSetIndexed(
|
|||
FlowGraph::kValue);
|
||||
}
|
||||
|
||||
intptr_t index_scale = FlowGraphCompiler::ElementSizeFor(array_cid);
|
||||
const intptr_t index_scale = Instance::ElementSizeFor(array_cid);
|
||||
*last = new StoreIndexedInstr(new Value(array),
|
||||
new Value(index),
|
||||
new Value(stored_value),
|
||||
|
@ -1653,7 +1653,7 @@ bool FlowGraphOptimizer::InlineGetIndexed(MethodRecognizer::Kind kind,
|
|||
}
|
||||
|
||||
// Array load and return.
|
||||
intptr_t index_scale = FlowGraphCompiler::ElementSizeFor(array_cid);
|
||||
intptr_t index_scale = Instance::ElementSizeFor(array_cid);
|
||||
*last = new LoadIndexedInstr(new Value(array),
|
||||
new Value(index),
|
||||
index_scale,
|
||||
|
@ -2724,7 +2724,7 @@ Definition* FlowGraphOptimizer::PrepareInlineStringIndexOp(
|
|||
LoadIndexedInstr* load_indexed = new LoadIndexedInstr(
|
||||
new Value(str),
|
||||
new Value(index),
|
||||
FlowGraphCompiler::ElementSizeFor(cid),
|
||||
Instance::ElementSizeFor(cid),
|
||||
cid,
|
||||
Isolate::kNoDeoptId,
|
||||
call->token_pos());
|
||||
|
@ -3708,7 +3708,7 @@ intptr_t FlowGraphOptimizer::PrepareInlineByteArrayViewOp(
|
|||
NULL,
|
||||
FlowGraph::kValue);
|
||||
|
||||
intptr_t element_size = FlowGraphCompiler::ElementSizeFor(array_cid);
|
||||
intptr_t element_size = Instance::ElementSizeFor(array_cid);
|
||||
ConstantInstr* bytes_per_element =
|
||||
flow_graph()->GetConstant(Smi::Handle(Smi::New(element_size)));
|
||||
BinarySmiOpInstr* len_in_bytes =
|
||||
|
@ -3721,7 +3721,7 @@ intptr_t FlowGraphOptimizer::PrepareInlineByteArrayViewOp(
|
|||
|
||||
ConstantInstr* length_adjustment =
|
||||
flow_graph()->GetConstant(Smi::Handle(Smi::New(
|
||||
FlowGraphCompiler::ElementSizeFor(view_cid) - 1)));
|
||||
Instance::ElementSizeFor(view_cid) - 1)));
|
||||
// adjusted_length = len_in_bytes - (element_size - 1).
|
||||
BinarySmiOpInstr* adjusted_length =
|
||||
new BinarySmiOpInstr(Token::kSUB,
|
||||
|
|
|
@ -1203,7 +1203,7 @@ void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
|||
if (!IsExternal()) {
|
||||
ASSERT(this->array()->definition()->representation() == kTagged);
|
||||
__ AddImmediate(idx,
|
||||
FlowGraphCompiler::DataOffsetFor(class_id()) - kHeapObjectTag);
|
||||
Instance::DataOffsetFor(class_id()) - kHeapObjectTag);
|
||||
}
|
||||
Address element_address(idx);
|
||||
const QRegister result = locs()->out(0).fpu_reg();
|
||||
|
@ -1239,7 +1239,7 @@ void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
|||
ASSERT(kSmiTagShift == 1);
|
||||
const intptr_t offset = IsExternal()
|
||||
? 0
|
||||
: FlowGraphCompiler::DataOffsetFor(class_id()) - kHeapObjectTag;
|
||||
: Instance::DataOffsetFor(class_id()) - kHeapObjectTag;
|
||||
switch (index_scale()) {
|
||||
case 1: {
|
||||
__ add(index.reg(), array, ShifterOperand(index.reg(), ASR, kSmiTagSize));
|
||||
|
@ -1250,7 +1250,7 @@ void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
|||
// No scaling needed, since index is a smi.
|
||||
if (!IsExternal()) {
|
||||
__ AddImmediate(index.reg(), index.reg(),
|
||||
FlowGraphCompiler::DataOffsetFor(class_id()) - kHeapObjectTag);
|
||||
Instance::DataOffsetFor(class_id()) - kHeapObjectTag);
|
||||
element_address = Address(array, index.reg(), LSL, 0);
|
||||
} else {
|
||||
element_address = Address(array, index.reg(), LSL, 0);
|
||||
|
@ -1470,7 +1470,7 @@ void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
|||
if (!IsExternal()) {
|
||||
ASSERT(this->array()->definition()->representation() == kTagged);
|
||||
__ AddImmediate(idx,
|
||||
FlowGraphCompiler::DataOffsetFor(class_id()) - kHeapObjectTag);
|
||||
Instance::DataOffsetFor(class_id()) - kHeapObjectTag);
|
||||
}
|
||||
switch (class_id()) {
|
||||
case kTypedDataFloat32ArrayCid: {
|
||||
|
@ -1508,7 +1508,7 @@ void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
|||
ASSERT(kSmiTagShift == 1);
|
||||
const intptr_t offset = IsExternal()
|
||||
? 0
|
||||
: FlowGraphCompiler::DataOffsetFor(class_id()) - kHeapObjectTag;
|
||||
: Instance::DataOffsetFor(class_id()) - kHeapObjectTag;
|
||||
switch (index_scale()) {
|
||||
case 1: {
|
||||
__ add(index.reg(), array, ShifterOperand(index.reg(), ASR, kSmiTagSize));
|
||||
|
|
|
@ -1010,7 +1010,7 @@ void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
|||
intptr_t offset = 0;
|
||||
if (!IsExternal()) {
|
||||
ASSERT(this->array()->definition()->representation() == kTagged);
|
||||
offset = FlowGraphCompiler::DataOffsetFor(class_id()) - kHeapObjectTag;
|
||||
offset = Instance::DataOffsetFor(class_id()) - kHeapObjectTag;
|
||||
}
|
||||
|
||||
// Note that index is expected smi-tagged, (i.e, times 2) for all arrays
|
||||
|
@ -1204,7 +1204,7 @@ void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
|||
intptr_t offset = 0;
|
||||
if (!IsExternal()) {
|
||||
ASSERT(this->array()->definition()->representation() == kTagged);
|
||||
offset = FlowGraphCompiler::DataOffsetFor(class_id()) - kHeapObjectTag;
|
||||
offset = Instance::DataOffsetFor(class_id()) - kHeapObjectTag;
|
||||
}
|
||||
|
||||
// Note that index is expected smi-tagged, (i.e, times 2) for all arrays
|
||||
|
|
|
@ -822,8 +822,8 @@ static bool CanBeImmediateIndex(Value* value, intptr_t cid) {
|
|||
return false;
|
||||
}
|
||||
const int64_t index = Smi::Cast(constant->value()).AsInt64Value();
|
||||
const intptr_t scale = FlowGraphCompiler::ElementSizeFor(cid);
|
||||
const intptr_t offset = FlowGraphCompiler::DataOffsetFor(cid);
|
||||
const intptr_t scale = Instance::ElementSizeFor(cid);
|
||||
const intptr_t offset = Instance::DataOffsetFor(cid);
|
||||
const int64_t displacement = index * scale + offset;
|
||||
return Utils::IsInt(32, displacement);
|
||||
}
|
||||
|
@ -1060,26 +1060,66 @@ LocationSummary* LoadIndexedInstr::MakeLocationSummary(Isolate* isolate,
|
|||
}
|
||||
|
||||
|
||||
static Address ElementAddressForIntIndex(bool is_external,
|
||||
intptr_t cid,
|
||||
intptr_t index_scale,
|
||||
Register array,
|
||||
intptr_t index) {
|
||||
if (is_external) {
|
||||
return Address(array, index * index_scale);
|
||||
} else {
|
||||
const int64_t disp = static_cast<int64_t>(index) * index_scale +
|
||||
Instance::DataOffsetFor(cid);
|
||||
ASSERT(Utils::IsInt(32, disp));
|
||||
return FieldAddress(array, static_cast<int32_t>(disp));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static ScaleFactor ToScaleFactor(intptr_t index_scale) {
|
||||
// Note that index is expected smi-tagged, (i.e, times 2) for all arrays with
|
||||
// index scale factor > 1. E.g., for Uint8Array and OneByteString the index is
|
||||
// expected to be untagged before accessing.
|
||||
ASSERT(kSmiTagShift == 1);
|
||||
switch (index_scale) {
|
||||
case 1: return TIMES_1;
|
||||
case 2: return TIMES_1;
|
||||
case 4: return TIMES_2;
|
||||
case 8: return TIMES_4;
|
||||
case 16: return TIMES_8;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return TIMES_1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static Address ElementAddressForRegIndex(bool is_external,
|
||||
intptr_t cid,
|
||||
intptr_t index_scale,
|
||||
Register array,
|
||||
Register index) {
|
||||
if (is_external) {
|
||||
return Address(array, index, ToScaleFactor(index_scale), 0);
|
||||
} else {
|
||||
return FieldAddress(array,
|
||||
index,
|
||||
ToScaleFactor(index_scale),
|
||||
Instance::DataOffsetFor(cid));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
Register array = locs()->in(0).reg();
|
||||
Location index = locs()->in(1);
|
||||
|
||||
Address element_address(kNoRegister, 0);
|
||||
if (IsExternal()) {
|
||||
element_address = index.IsRegister()
|
||||
? compiler->ExternalElementAddressForRegIndex(
|
||||
index_scale(), array, index.reg())
|
||||
: compiler->ExternalElementAddressForIntIndex(
|
||||
index_scale(), array, Smi::Cast(index.constant()).Value());
|
||||
} else {
|
||||
ASSERT(this->array()->definition()->representation() == kTagged);
|
||||
element_address = index.IsRegister()
|
||||
? compiler->ElementAddressForRegIndex(
|
||||
class_id(), index_scale(), array, index.reg())
|
||||
: compiler->ElementAddressForIntIndex(
|
||||
class_id(), index_scale(), array,
|
||||
Smi::Cast(index.constant()).Value());
|
||||
}
|
||||
element_address = index.IsRegister()
|
||||
? ElementAddressForRegIndex(IsExternal(), class_id(), index_scale(),
|
||||
array, index.reg())
|
||||
: ElementAddressForIntIndex(IsExternal(), class_id(), index_scale(),
|
||||
array, Smi::Cast(index.constant()).Value());
|
||||
|
||||
if ((representation() == kUnboxedDouble) ||
|
||||
(representation() == kUnboxedFloat32x4) ||
|
||||
|
@ -1300,21 +1340,11 @@ void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
|||
Location index = locs()->in(1);
|
||||
|
||||
Address element_address(kNoRegister, 0);
|
||||
if (IsExternal()) {
|
||||
element_address = index.IsRegister()
|
||||
? compiler->ExternalElementAddressForRegIndex(
|
||||
index_scale(), array, index.reg())
|
||||
: compiler->ExternalElementAddressForIntIndex(
|
||||
index_scale(), array, Smi::Cast(index.constant()).Value());
|
||||
} else {
|
||||
ASSERT(this->array()->definition()->representation() == kTagged);
|
||||
element_address = index.IsRegister()
|
||||
? compiler->ElementAddressForRegIndex(
|
||||
class_id(), index_scale(), array, index.reg())
|
||||
: compiler->ElementAddressForIntIndex(
|
||||
class_id(), index_scale(), array,
|
||||
Smi::Cast(index.constant()).Value());
|
||||
}
|
||||
element_address = index.IsRegister()
|
||||
? ElementAddressForRegIndex(IsExternal(), class_id(), index_scale(),
|
||||
array, index.reg())
|
||||
: ElementAddressForIntIndex(IsExternal(), class_id(), index_scale(),
|
||||
array, Smi::Cast(index.constant()).Value());
|
||||
|
||||
if ((index_scale() == 1) && index.IsRegister()) {
|
||||
__ SmiUntag(index.reg());
|
||||
|
|
|
@ -1165,7 +1165,7 @@ void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
|||
// mode, then we must load the offset into a register and add it to the
|
||||
// index.
|
||||
element_address = Address(index.reg(),
|
||||
FlowGraphCompiler::DataOffsetFor(class_id()) - kHeapObjectTag);
|
||||
Instance::DataOffsetFor(class_id()) - kHeapObjectTag);
|
||||
}
|
||||
|
||||
if ((representation() == kUnboxedDouble) ||
|
||||
|
@ -1186,7 +1186,7 @@ void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
|||
break;
|
||||
case kTypedDataFloat64ArrayCid:
|
||||
__ LoadDFromOffset(result, index.reg(),
|
||||
FlowGraphCompiler::DataOffsetFor(class_id()) - kHeapObjectTag);
|
||||
Instance::DataOffsetFor(class_id()) - kHeapObjectTag);
|
||||
break;
|
||||
case kTypedDataInt32x4ArrayCid:
|
||||
case kTypedDataFloat32x4ArrayCid:
|
||||
|
@ -1371,7 +1371,7 @@ void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
|||
} else {
|
||||
ASSERT(this->array()->definition()->representation() == kTagged);
|
||||
element_address = Address(index.reg(),
|
||||
FlowGraphCompiler::DataOffsetFor(class_id()) - kHeapObjectTag);
|
||||
Instance::DataOffsetFor(class_id()) - kHeapObjectTag);
|
||||
}
|
||||
|
||||
switch (class_id()) {
|
||||
|
@ -1455,7 +1455,7 @@ void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
|||
}
|
||||
case kTypedDataFloat64ArrayCid:
|
||||
__ StoreDToOffset(locs()->in(2).fpu_reg(), index.reg(),
|
||||
FlowGraphCompiler::DataOffsetFor(class_id()) - kHeapObjectTag);
|
||||
Instance::DataOffsetFor(class_id()) - kHeapObjectTag);
|
||||
break;
|
||||
case kTypedDataInt32x4ArrayCid:
|
||||
case kTypedDataFloat32x4ArrayCid:
|
||||
|
|
|
@ -751,8 +751,8 @@ static bool CanBeImmediateIndex(Value* index, intptr_t cid) {
|
|||
const Object& constant = index->definition()->AsConstant()->value();
|
||||
if (!constant.IsSmi()) return false;
|
||||
const Smi& smi_const = Smi::Cast(constant);
|
||||
const intptr_t scale = FlowGraphCompiler::ElementSizeFor(cid);
|
||||
const intptr_t data_offset = FlowGraphCompiler::DataOffsetFor(cid);
|
||||
const intptr_t scale = Instance::ElementSizeFor(cid);
|
||||
const intptr_t data_offset = Instance::DataOffsetFor(cid);
|
||||
const int64_t disp = smi_const.AsInt64Value() * scale + data_offset;
|
||||
return Utils::IsInt(32, disp);
|
||||
}
|
||||
|
@ -973,29 +973,66 @@ LocationSummary* LoadIndexedInstr::MakeLocationSummary(Isolate* isolate,
|
|||
}
|
||||
|
||||
|
||||
static Address ElementAddressForIntIndex(bool is_external,
|
||||
intptr_t cid,
|
||||
intptr_t index_scale,
|
||||
Register array,
|
||||
intptr_t index) {
|
||||
if (is_external) {
|
||||
return Address(array, index * index_scale);
|
||||
} else {
|
||||
const int64_t disp = static_cast<int64_t>(index) * index_scale +
|
||||
Instance::DataOffsetFor(cid);
|
||||
ASSERT(Utils::IsInt(32, disp));
|
||||
return FieldAddress(array, static_cast<int32_t>(disp));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static ScaleFactor ToScaleFactor(intptr_t index_scale) {
|
||||
// Note that index is expected smi-tagged, (i.e, times 2) for all arrays with
|
||||
// index scale factor > 1. E.g., for Uint8Array and OneByteString the index is
|
||||
// expected to be untagged before accessing.
|
||||
ASSERT(kSmiTagShift == 1);
|
||||
switch (index_scale) {
|
||||
case 1: return TIMES_1;
|
||||
case 2: return TIMES_1;
|
||||
case 4: return TIMES_2;
|
||||
case 8: return TIMES_4;
|
||||
case 16: return TIMES_8;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return TIMES_1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static Address ElementAddressForRegIndex(bool is_external,
|
||||
intptr_t cid,
|
||||
intptr_t index_scale,
|
||||
Register array,
|
||||
Register index) {
|
||||
if (is_external) {
|
||||
return Address(array, index, ToScaleFactor(index_scale), 0);
|
||||
} else {
|
||||
return FieldAddress(array,
|
||||
index,
|
||||
ToScaleFactor(index_scale),
|
||||
Instance::DataOffsetFor(cid));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
Register array = locs()->in(0).reg();
|
||||
Location index = locs()->in(1);
|
||||
|
||||
const bool is_external =
|
||||
(this->array()->definition()->representation() == kUntagged);
|
||||
Address element_address(kNoRegister, 0);
|
||||
|
||||
if (is_external) {
|
||||
element_address = index.IsRegister()
|
||||
? compiler->ExternalElementAddressForRegIndex(
|
||||
index_scale(), array, index.reg())
|
||||
: compiler->ExternalElementAddressForIntIndex(
|
||||
index_scale(), array, Smi::Cast(index.constant()).Value());
|
||||
} else {
|
||||
ASSERT(this->array()->definition()->representation() == kTagged);
|
||||
element_address = index.IsRegister()
|
||||
? compiler->ElementAddressForRegIndex(
|
||||
class_id(), index_scale(), array, index.reg())
|
||||
: compiler->ElementAddressForIntIndex(
|
||||
class_id(), index_scale(), array,
|
||||
Smi::Cast(index.constant()).Value());
|
||||
}
|
||||
element_address = index.IsRegister()
|
||||
? ElementAddressForRegIndex(IsExternal(), class_id(), index_scale(),
|
||||
array, index.reg())
|
||||
: ElementAddressForIntIndex(IsExternal(), class_id(), index_scale(),
|
||||
array, Smi::Cast(index.constant()).Value());
|
||||
|
||||
if ((representation() == kUnboxedDouble) ||
|
||||
(representation() == kUnboxedFloat32x4) ||
|
||||
|
@ -1161,24 +1198,12 @@ void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
|||
Register array = locs()->in(0).reg();
|
||||
Location index = locs()->in(1);
|
||||
|
||||
const bool is_external =
|
||||
(this->array()->definition()->representation() == kUntagged);
|
||||
Address element_address(kNoRegister, 0);
|
||||
if (is_external) {
|
||||
element_address = index.IsRegister()
|
||||
? compiler->ExternalElementAddressForRegIndex(
|
||||
index_scale(), array, index.reg())
|
||||
: compiler->ExternalElementAddressForIntIndex(
|
||||
index_scale(), array, Smi::Cast(index.constant()).Value());
|
||||
} else {
|
||||
ASSERT(this->array()->definition()->representation() == kTagged);
|
||||
element_address = index.IsRegister()
|
||||
? compiler->ElementAddressForRegIndex(
|
||||
class_id(), index_scale(), array, index.reg())
|
||||
: compiler->ElementAddressForIntIndex(
|
||||
class_id(), index_scale(), array,
|
||||
Smi::Cast(index.constant()).Value());
|
||||
}
|
||||
element_address = index.IsRegister()
|
||||
? ElementAddressForRegIndex(IsExternal(), class_id(), index_scale(),
|
||||
array, index.reg())
|
||||
: ElementAddressForIntIndex(IsExternal(), class_id(), index_scale(),
|
||||
array, Smi::Cast(index.constant()).Value());
|
||||
|
||||
if ((index_scale() == 1) && index.IsRegister()) {
|
||||
__ SmiUntag(index.reg());
|
||||
|
|
|
@ -1249,12 +1249,9 @@ void Intrinsifier::Random_nextState(Assembler* assembler) {
|
|||
__ ldr(R1, FieldAddress(R0, state_field.Offset())); // Field '_state'.
|
||||
// Addresses of _state[0] and _state[1].
|
||||
|
||||
const int64_t disp_0 =
|
||||
FlowGraphCompiler::DataOffsetFor(kTypedDataUint32ArrayCid);
|
||||
|
||||
const int64_t disp_1 =
|
||||
FlowGraphCompiler::ElementSizeFor(kTypedDataUint32ArrayCid) +
|
||||
FlowGraphCompiler::DataOffsetFor(kTypedDataUint32ArrayCid);
|
||||
const int64_t disp_0 = Instance::DataOffsetFor(kTypedDataUint32ArrayCid);
|
||||
const int64_t disp_1 = disp_0 +
|
||||
Instance::ElementSizeFor(kTypedDataUint32ArrayCid);
|
||||
|
||||
__ LoadImmediate(R0, a_int32_value);
|
||||
__ LoadFromOffset(kWord, R2, R1, disp_0 - kHeapObjectTag);
|
||||
|
|
|
@ -1134,8 +1134,7 @@ void Intrinsifier::Random_nextState(Assembler* assembler) {
|
|||
|
||||
// Addresses of _state[0].
|
||||
const int64_t disp =
|
||||
FlowGraphCompiler::DataOffsetFor(kTypedDataUint32ArrayCid) -
|
||||
kHeapObjectTag;
|
||||
Instance::DataOffsetFor(kTypedDataUint32ArrayCid) - kHeapObjectTag;
|
||||
|
||||
__ LoadImmediate(R0, a_int_value, kNoPP);
|
||||
__ LoadFromOffset(R2, R1, disp, kNoPP);
|
||||
|
|
|
@ -1248,12 +1248,10 @@ void Intrinsifier::Random_nextState(Assembler* assembler) {
|
|||
__ movl(EAX, Address(ESP, + 1 * kWordSize)); // Receiver.
|
||||
__ movl(EBX, FieldAddress(EAX, state_field.Offset())); // Field '_state'.
|
||||
// Addresses of _state[0] and _state[1].
|
||||
const intptr_t index_scale =
|
||||
FlowGraphCompiler::ElementSizeFor(kTypedDataUint32ArrayCid);
|
||||
const intptr_t offset =
|
||||
FlowGraphCompiler::DataOffsetFor(kTypedDataUint32ArrayCid);
|
||||
Address addr_0 = FieldAddress(EBX, 0 * index_scale + offset);
|
||||
Address addr_1 = FieldAddress(EBX, 1 * index_scale + offset);
|
||||
const intptr_t scale = Instance::ElementSizeFor(kTypedDataUint32ArrayCid);
|
||||
const intptr_t offset = Instance::DataOffsetFor(kTypedDataUint32ArrayCid);
|
||||
Address addr_0 = FieldAddress(EBX, 0 * scale + offset);
|
||||
Address addr_1 = FieldAddress(EBX, 1 * scale + offset);
|
||||
__ movl(EAX, Immediate(a_int32_value));
|
||||
// 64-bit multiply EAX * value -> EDX:EAX.
|
||||
__ mull(addr_0);
|
||||
|
|
|
@ -1275,12 +1275,10 @@ void Intrinsifier::Random_nextState(Assembler* assembler) {
|
|||
__ lw(T1, FieldAddress(T0, state_field.Offset())); // Field '_state'.
|
||||
|
||||
// Addresses of _state[0] and _state[1].
|
||||
const Address& addr_0 = FieldAddress(T1,
|
||||
FlowGraphCompiler::DataOffsetFor(kTypedDataUint32ArrayCid));
|
||||
|
||||
const Address& addr_1 = FieldAddress(T1,
|
||||
FlowGraphCompiler::ElementSizeFor(kTypedDataUint32ArrayCid) +
|
||||
FlowGraphCompiler::DataOffsetFor(kTypedDataUint32ArrayCid));
|
||||
const intptr_t scale = Instance::ElementSizeFor(kTypedDataUint32ArrayCid);
|
||||
const intptr_t offset = Instance::DataOffsetFor(kTypedDataUint32ArrayCid);
|
||||
const Address& addr_0 = FieldAddress(T1, 0 * scale + offset);
|
||||
const Address& addr_1 = FieldAddress(T1, 1 * scale + offset);
|
||||
|
||||
__ LoadImmediate(T0, a_int32_value);
|
||||
__ lw(T2, addr_0);
|
||||
|
|
|
@ -1150,12 +1150,10 @@ void Intrinsifier::Random_nextState(Assembler* assembler) {
|
|||
__ movq(RAX, Address(RSP, + 1 * kWordSize)); // Receiver.
|
||||
__ movq(RBX, FieldAddress(RAX, state_field.Offset())); // Field '_state'.
|
||||
// Addresses of _state[0] and _state[1].
|
||||
const intptr_t index_scale =
|
||||
FlowGraphCompiler::ElementSizeFor(kTypedDataUint32ArrayCid);
|
||||
const intptr_t offset =
|
||||
FlowGraphCompiler::DataOffsetFor(kTypedDataUint32ArrayCid);
|
||||
Address addr_0 = FieldAddress(RBX, 0 * index_scale + offset);
|
||||
Address addr_1 = FieldAddress(RBX, 1 * index_scale + offset);
|
||||
const intptr_t scale = Instance::ElementSizeFor(kTypedDataUint32ArrayCid);
|
||||
const intptr_t offset = Instance::DataOffsetFor(kTypedDataUint32ArrayCid);
|
||||
Address addr_0 = FieldAddress(RBX, 0 * scale + offset);
|
||||
Address addr_1 = FieldAddress(RBX, 1 * scale + offset);
|
||||
__ movq(RAX, Immediate(a_int_value));
|
||||
__ movl(RCX, addr_0);
|
||||
__ imulq(RCX, RAX);
|
||||
|
|
|
@ -13054,6 +13054,50 @@ bool Instance::IsValidFieldOffset(intptr_t offset) const {
|
|||
}
|
||||
|
||||
|
||||
intptr_t Instance::ElementSizeFor(intptr_t cid) {
|
||||
if (RawObject::IsExternalTypedDataClassId(cid)) {
|
||||
return ExternalTypedData::ElementSizeInBytes(cid);
|
||||
} else if (RawObject::IsTypedDataClassId(cid)) {
|
||||
return TypedData::ElementSizeInBytes(cid);
|
||||
}
|
||||
switch (cid) {
|
||||
case kArrayCid:
|
||||
case kImmutableArrayCid:
|
||||
return Array::kBytesPerElement;
|
||||
case kOneByteStringCid:
|
||||
return OneByteString::kBytesPerElement;
|
||||
case kTwoByteStringCid:
|
||||
return TwoByteString::kBytesPerElement;
|
||||
default:
|
||||
UNIMPLEMENTED();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
intptr_t Instance::DataOffsetFor(intptr_t cid) {
|
||||
if (RawObject::IsExternalTypedDataClassId(cid)) {
|
||||
// Elements start at offset 0 of the external data.
|
||||
return 0;
|
||||
}
|
||||
if (RawObject::IsTypedDataClassId(cid)) {
|
||||
return TypedData::data_offset();
|
||||
}
|
||||
switch (cid) {
|
||||
case kArrayCid:
|
||||
case kImmutableArrayCid:
|
||||
return Array::data_offset();
|
||||
case kOneByteStringCid:
|
||||
return OneByteString::data_offset();
|
||||
case kTwoByteStringCid:
|
||||
return TwoByteString::data_offset();
|
||||
default:
|
||||
UNIMPLEMENTED();
|
||||
return Array::data_offset();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const char* Instance::ToCString() const {
|
||||
if (IsNull()) {
|
||||
return "null";
|
||||
|
|
|
@ -4212,6 +4212,10 @@ class Instance : public Object {
|
|||
|
||||
static RawInstance* New(const Class& cls, Heap::Space space = Heap::kNew);
|
||||
|
||||
// Array/list element address computations.
|
||||
static intptr_t DataOffsetFor(intptr_t cid);
|
||||
static intptr_t ElementSizeFor(intptr_t cid);
|
||||
|
||||
protected:
|
||||
virtual void PrintSharedInstanceJSON(JSONObject* jsobj, bool ref) const;
|
||||
|
||||
|
|
Loading…
Reference in a new issue