| Index: runtime/vm/flow_graph_optimizer.cc
|
| ===================================================================
|
| --- runtime/vm/flow_graph_optimizer.cc (revision 20148)
|
| +++ runtime/vm/flow_graph_optimizer.cc (working copy)
|
| @@ -375,7 +375,7 @@
|
| Value* use = it.Current();
|
| const Representation to_rep =
|
| use->instruction()->RequiredInputRepresentation(use->use_index());
|
| - if (from_rep == to_rep) {
|
| + if (from_rep == to_rep || to_rep == kNoRepresentation) {
|
| continue;
|
| }
|
|
|
| @@ -688,6 +688,13 @@
|
| *array = elements;
|
| return kArrayCid;
|
| }
|
| + if (RawObject::IsExternalTypedDataClassId(class_id)) {
|
| + LoadUntaggedInstr* elements =
|
| + new LoadUntaggedInstr(new Value(*array),
|
| + ExternalTypedData::data_offset());
|
| + InsertBefore(call, elements, NULL, Definition::kValue);
|
| + *array = elements;
|
| + }
|
| return class_id;
|
| }
|
|
|
| @@ -709,13 +716,6 @@
|
| value_check = call->ic_data()->AsUnaryClassChecksForArgNr(2);
|
| }
|
| break;
|
| - case kInt8ArrayCid:
|
| - case kUint8ArrayCid:
|
| - case kUint8ClampedArrayCid:
|
| - case kExternalUint8ArrayCid:
|
| - case kExternalUint8ClampedArrayCid:
|
| - case kInt16ArrayCid:
|
| - case kUint16ArrayCid:
|
| case kTypedDataInt8ArrayCid:
|
| case kTypedDataUint8ArrayCid:
|
| case kTypedDataUint8ClampedArrayCid:
|
| @@ -730,8 +730,6 @@
|
| return false;
|
| }
|
| break;
|
| - case kInt32ArrayCid:
|
| - case kUint32ArrayCid:
|
| case kTypedDataInt32ArrayCid:
|
| case kTypedDataUint32ArrayCid: {
|
| if (!CanUnboxInt32()) return false;
|
| @@ -750,8 +748,6 @@
|
| }
|
| break;
|
| }
|
| - case kFloat32ArrayCid:
|
| - case kFloat64ArrayCid:
|
| case kTypedDataFloat32ArrayCid:
|
| case kTypedDataFloat64ArrayCid: {
|
| // Check that value is always double.
|
| @@ -772,58 +768,6 @@
|
| }
|
|
|
|
|
| -bool FlowGraphOptimizer::TryInlineByteArraySetIndexed(InstanceCallInstr* call) {
|
| - const intptr_t class_id = ReceiverClassId(call);
|
| - ICData& value_check = ICData::ZoneHandle();
|
| - switch (class_id) {
|
| - case kInt8ArrayCid:
|
| - case kUint8ArrayCid:
|
| - case kUint8ClampedArrayCid:
|
| - case kExternalUint8ArrayCid:
|
| - case kExternalUint8ClampedArrayCid:
|
| - case kInt16ArrayCid:
|
| - case kUint16ArrayCid: {
|
| - // Check that value is always smi.
|
| - value_check = ICData::New(Function::Handle(),
|
| - String::Handle(),
|
| - Isolate::kNoDeoptId,
|
| - 1);
|
| - value_check.AddReceiverCheck(kSmiCid, Function::Handle());
|
| - break;
|
| - }
|
| - case kInt32ArrayCid:
|
| - case kUint32ArrayCid:
|
| - if (!CanUnboxInt32()) return false;
|
| -
|
| - // We don't have ICData for the value stored, so we optimistically assume
|
| - // smis first. If we ever deoptimized here, we require to unbox the value
|
| - // before storing to handle the mint case, too.
|
| - if (call->ic_data()->deopt_reason() == kDeoptUnknown) {
|
| - value_check = ICData::New(Function::Handle(),
|
| - String::Handle(),
|
| - Isolate::kNoDeoptId,
|
| - 1);
|
| - value_check.AddReceiverCheck(kSmiCid, Function::Handle());
|
| - }
|
| - break;
|
| - case kFloat32ArrayCid:
|
| - case kFloat64ArrayCid: {
|
| - // Check that value is always double.
|
| - value_check = ICData::New(Function::Handle(),
|
| - String::Handle(),
|
| - Isolate::kNoDeoptId,
|
| - 1);
|
| - value_check.AddReceiverCheck(kDoubleCid, Function::Handle());
|
| - break;
|
| - }
|
| - default:
|
| - return false;
|
| - }
|
| - BuildStoreIndexed(call, value_check, class_id);
|
| - return true;
|
| -}
|
| -
|
| -
|
| void FlowGraphOptimizer::BuildStoreIndexed(InstanceCallInstr* call,
|
| const ICData& value_check,
|
| intptr_t class_id) {
|
| @@ -855,15 +799,6 @@
|
| type_args = load_type_args;
|
| break;
|
| }
|
| - case kInt8ArrayCid:
|
| - case kUint8ArrayCid:
|
| - case kUint8ClampedArrayCid:
|
| - case kExternalUint8ArrayCid:
|
| - case kExternalUint8ClampedArrayCid:
|
| - case kInt16ArrayCid:
|
| - case kUint16ArrayCid:
|
| - case kInt32ArrayCid:
|
| - case kUint32ArrayCid:
|
| case kTypedDataInt8ArrayCid:
|
| case kTypedDataUint8ArrayCid:
|
| case kTypedDataUint8ClampedArrayCid:
|
| @@ -875,8 +810,6 @@
|
| case kTypedDataUint32ArrayCid:
|
| ASSERT(value_type.IsIntType());
|
| // Fall through.
|
| - case kFloat32ArrayCid:
|
| - case kFloat64ArrayCid:
|
| case kTypedDataFloat32ArrayCid:
|
| case kTypedDataFloat64ArrayCid: {
|
| type_args = instantiator = flow_graph_->constant_null();
|
| @@ -941,15 +874,6 @@
|
| case kArrayCid:
|
| case kImmutableArrayCid:
|
| case kGrowableObjectArrayCid:
|
| - case kFloat32ArrayCid:
|
| - case kFloat64ArrayCid:
|
| - case kInt8ArrayCid:
|
| - case kUint8ArrayCid:
|
| - case kUint8ClampedArrayCid:
|
| - case kExternalUint8ArrayCid:
|
| - case kExternalUint8ClampedArrayCid:
|
| - case kInt16ArrayCid:
|
| - case kUint16ArrayCid:
|
| case kTypedDataFloat32ArrayCid:
|
| case kTypedDataFloat64ArrayCid:
|
| case kTypedDataInt8ArrayCid:
|
| @@ -960,8 +884,6 @@
|
| case kTypedDataInt16ArrayCid:
|
| case kTypedDataUint16ArrayCid:
|
| break;
|
| - case kInt32ArrayCid:
|
| - case kUint32ArrayCid:
|
| case kTypedDataInt32ArrayCid:
|
| case kTypedDataUint32ArrayCid: {
|
| if (!CanUnboxInt32()) return false;
|
| @@ -1361,8 +1283,6 @@
|
| case MethodRecognizer::kObjectArrayLength:
|
| case MethodRecognizer::kImmutableArrayLength:
|
| return Array::length_offset();
|
| - case MethodRecognizer::kByteArrayBaseLength:
|
| - return ByteArray::length_offset();
|
| case MethodRecognizer::kTypedDataLength:
|
| // .length is defined in _TypedList which is the base class for internal
|
| // and external typed data.
|
| @@ -1405,7 +1325,6 @@
|
| switch (recognized_kind) {
|
| case MethodRecognizer::kObjectArrayLength:
|
| case MethodRecognizer::kImmutableArrayLength:
|
| - case MethodRecognizer::kByteArrayBaseLength:
|
| case MethodRecognizer::kTypedDataLength:
|
| case MethodRecognizer::kGrowableArrayLength: {
|
| if (!ic_data.HasOneTarget()) {
|
| @@ -1415,7 +1334,6 @@
|
| const bool is_immutable =
|
| (recognized_kind == MethodRecognizer::kObjectArrayLength) ||
|
| (recognized_kind == MethodRecognizer::kImmutableArrayLength) ||
|
| - (recognized_kind == MethodRecognizer::kByteArrayBaseLength) ||
|
| (recognized_kind == MethodRecognizer::kTypedDataLength);
|
| InlineArrayLengthGetter(call,
|
| OffsetForLengthGetter(recognized_kind),
|
| @@ -1504,15 +1422,17 @@
|
|
|
| static bool IsSupportedByteArrayViewCid(intptr_t cid) {
|
| switch (cid) {
|
| - case kInt8ArrayCid:
|
| - case kUint8ArrayCid:
|
| - case kUint8ClampedArrayCid:
|
| - case kInt16ArrayCid:
|
| - case kUint16ArrayCid:
|
| - case kInt32ArrayCid:
|
| - case kUint32ArrayCid:
|
| - case kFloat32ArrayCid:
|
| - case kFloat64ArrayCid:
|
| + case kTypedDataInt8ArrayCid:
|
| + case kTypedDataUint8ArrayCid:
|
| + case kExternalTypedDataUint8ArrayCid:
|
| + case kTypedDataUint8ClampedArrayCid:
|
| + case kExternalTypedDataUint8ClampedArrayCid:
|
| + case kTypedDataInt16ArrayCid:
|
| + case kTypedDataUint16ArrayCid:
|
| + case kTypedDataInt32ArrayCid:
|
| + case kTypedDataUint32ArrayCid:
|
| + case kTypedDataFloat32ArrayCid:
|
| + case kTypedDataFloat64ArrayCid:
|
| return true;
|
| default:
|
| return false;
|
| @@ -1535,38 +1455,6 @@
|
| MethodRecognizer::Kind recognized_kind =
|
| MethodRecognizer::RecognizeKind(target);
|
|
|
| - // Byte array access.
|
| - switch (recognized_kind) {
|
| - case MethodRecognizer::kFloat32ArrayGetIndexed:
|
| - case MethodRecognizer::kFloat64ArrayGetIndexed:
|
| - case MethodRecognizer::kInt8ArrayGetIndexed:
|
| - case MethodRecognizer::kUint8ArrayGetIndexed:
|
| - case MethodRecognizer::kUint8ClampedArrayGetIndexed:
|
| - case MethodRecognizer::kExternalUint8ArrayGetIndexed:
|
| - case MethodRecognizer::kExternalUint8ClampedArrayGetIndexed:
|
| - case MethodRecognizer::kInt16ArrayGetIndexed:
|
| - case MethodRecognizer::kUint16ArrayGetIndexed:
|
| - case MethodRecognizer::kInt32ArrayGetIndexed:
|
| - case MethodRecognizer::kUint32ArrayGetIndexed:
|
| - return TryReplaceWithLoadIndexed(call);
|
| -
|
| - case MethodRecognizer::kFloat32ArraySetIndexed:
|
| - case MethodRecognizer::kFloat64ArraySetIndexed:
|
| - case MethodRecognizer::kInt8ArraySetIndexed:
|
| - case MethodRecognizer::kUint8ArraySetIndexed:
|
| - case MethodRecognizer::kUint8ClampedArraySetIndexed:
|
| - case MethodRecognizer::kExternalUint8ArraySetIndexed:
|
| - case MethodRecognizer::kExternalUint8ClampedArraySetIndexed:
|
| - case MethodRecognizer::kInt16ArraySetIndexed:
|
| - case MethodRecognizer::kUint16ArraySetIndexed:
|
| - case MethodRecognizer::kInt32ArraySetIndexed:
|
| - case MethodRecognizer::kUint32ArraySetIndexed:
|
| - return TryInlineByteArraySetIndexed(call);
|
| -
|
| - default:
|
| - break;
|
| - }
|
| -
|
| if ((recognized_kind == MethodRecognizer::kStringBaseCodeUnitAt) &&
|
| (ic_data.NumberOfChecks() == 1) &&
|
| ((class_ids[0] == kOneByteStringCid) ||
|
| @@ -1655,39 +1543,55 @@
|
| switch (recognized_kind) {
|
| // ByteArray getters.
|
| case MethodRecognizer::kByteArrayBaseGetInt8:
|
| - return BuildByteArrayViewLoad(call, class_ids[0], kInt8ArrayCid);
|
| + return BuildByteArrayViewLoad(
|
| + call, class_ids[0], kTypedDataInt8ArrayCid);
|
| case MethodRecognizer::kByteArrayBaseGetUint8:
|
| - return BuildByteArrayViewLoad(call, class_ids[0], kUint8ArrayCid);
|
| + return BuildByteArrayViewLoad(
|
| + call, class_ids[0], kTypedDataUint8ArrayCid);
|
| case MethodRecognizer::kByteArrayBaseGetInt16:
|
| - return BuildByteArrayViewLoad(call, class_ids[0], kInt16ArrayCid);
|
| + return BuildByteArrayViewLoad(
|
| + call, class_ids[0], kTypedDataInt16ArrayCid);
|
| case MethodRecognizer::kByteArrayBaseGetUint16:
|
| - return BuildByteArrayViewLoad(call, class_ids[0], kUint16ArrayCid);
|
| + return BuildByteArrayViewLoad(
|
| + call, class_ids[0], kTypedDataUint16ArrayCid);
|
| case MethodRecognizer::kByteArrayBaseGetInt32:
|
| - return BuildByteArrayViewLoad(call, class_ids[0], kInt32ArrayCid);
|
| + return BuildByteArrayViewLoad(
|
| + call, class_ids[0], kTypedDataInt32ArrayCid);
|
| case MethodRecognizer::kByteArrayBaseGetUint32:
|
| - return BuildByteArrayViewLoad(call, class_ids[0], kUint32ArrayCid);
|
| + return BuildByteArrayViewLoad(
|
| + call, class_ids[0], kTypedDataUint32ArrayCid);
|
| case MethodRecognizer::kByteArrayBaseGetFloat32:
|
| - return BuildByteArrayViewLoad(call, class_ids[0], kFloat32ArrayCid);
|
| + return BuildByteArrayViewLoad(
|
| + call, class_ids[0], kTypedDataFloat32ArrayCid);
|
| case MethodRecognizer::kByteArrayBaseGetFloat64:
|
| - return BuildByteArrayViewLoad(call, class_ids[0], kFloat64ArrayCid);
|
| + return BuildByteArrayViewLoad(
|
| + call, class_ids[0], kTypedDataFloat64ArrayCid);
|
|
|
| // ByteArray setters.
|
| case MethodRecognizer::kByteArrayBaseSetInt8:
|
| - return BuildByteArrayViewStore(call, class_ids[0], kInt8ArrayCid);
|
| + return BuildByteArrayViewStore(
|
| + call, class_ids[0], kTypedDataInt8ArrayCid);
|
| case MethodRecognizer::kByteArrayBaseSetUint8:
|
| - return BuildByteArrayViewStore(call, class_ids[0], kUint8ArrayCid);
|
| + return BuildByteArrayViewStore(
|
| + call, class_ids[0], kTypedDataUint8ArrayCid);
|
| case MethodRecognizer::kByteArrayBaseSetInt16:
|
| - return BuildByteArrayViewStore(call, class_ids[0], kInt16ArrayCid);
|
| + return BuildByteArrayViewStore(
|
| + call, class_ids[0], kTypedDataInt16ArrayCid);
|
| case MethodRecognizer::kByteArrayBaseSetUint16:
|
| - return BuildByteArrayViewStore(call, class_ids[0], kUint16ArrayCid);
|
| + return BuildByteArrayViewStore(
|
| + call, class_ids[0], kTypedDataUint16ArrayCid);
|
| case MethodRecognizer::kByteArrayBaseSetInt32:
|
| - return BuildByteArrayViewStore(call, class_ids[0], kInt32ArrayCid);
|
| + return BuildByteArrayViewStore(
|
| + call, class_ids[0], kTypedDataInt32ArrayCid);
|
| case MethodRecognizer::kByteArrayBaseSetUint32:
|
| - return BuildByteArrayViewStore(call, class_ids[0], kUint32ArrayCid);
|
| + return BuildByteArrayViewStore(
|
| + call, class_ids[0], kTypedDataUint32ArrayCid);
|
| case MethodRecognizer::kByteArrayBaseSetFloat32:
|
| - return BuildByteArrayViewStore(call, class_ids[0], kFloat32ArrayCid);
|
| + return BuildByteArrayViewStore(
|
| + call, class_ids[0], kTypedDataFloat32ArrayCid);
|
| case MethodRecognizer::kByteArrayBaseSetFloat64:
|
| - return BuildByteArrayViewStore(call, class_ids[0], kFloat64ArrayCid);
|
| + return BuildByteArrayViewStore(
|
| + call, class_ids[0], kTypedDataFloat64ArrayCid);
|
| default:
|
| // Unsupported method.
|
| return false;
|
| @@ -1701,10 +1605,8 @@
|
| InstanceCallInstr* call,
|
| intptr_t receiver_cid,
|
| intptr_t view_cid) {
|
| - PrepareByteArrayViewOp(call, receiver_cid, view_cid);
|
| -
|
| Definition* array = call->ArgumentAt(0);
|
| - Definition* byte_index = call->ArgumentAt(1);
|
| + PrepareByteArrayViewOp(call, receiver_cid, view_cid, &array);
|
|
|
| // Optimistically build a smi-checked load for Int32 and Uint32
|
| // loads on ia32 like we do for normal array loads, and only revert to
|
| @@ -1714,6 +1616,7 @@
|
| call->ic_data()->deopt_reason() == kDeoptUnknown) {
|
| deopt_id = call->deopt_id();
|
| }
|
| + Definition* byte_index = call->ArgumentAt(1);
|
| LoadIndexedInstr* array_op = new LoadIndexedInstr(new Value(array),
|
| new Value(byte_index),
|
| 1, // Index scale.
|
| @@ -1728,16 +1631,17 @@
|
| InstanceCallInstr* call,
|
| intptr_t receiver_cid,
|
| intptr_t view_cid) {
|
| - PrepareByteArrayViewOp(call, receiver_cid, view_cid);
|
| + Definition* array = call->ArgumentAt(0);
|
| + PrepareByteArrayViewOp(call, receiver_cid, view_cid, &array);
|
| ICData& value_check = ICData::ZoneHandle();
|
| switch (view_cid) {
|
| - case kInt8ArrayCid:
|
| - case kUint8ArrayCid:
|
| - case kUint8ClampedArrayCid:
|
| - case kExternalUint8ArrayCid:
|
| - case kExternalUint8ClampedArrayCid:
|
| - case kInt16ArrayCid:
|
| - case kUint16ArrayCid: {
|
| + case kTypedDataInt8ArrayCid:
|
| + case kTypedDataUint8ArrayCid:
|
| + case kTypedDataUint8ClampedArrayCid:
|
| + case kExternalTypedDataUint8ArrayCid:
|
| + case kExternalTypedDataUint8ClampedArrayCid:
|
| + case kTypedDataInt16ArrayCid:
|
| + case kTypedDataUint16ArrayCid: {
|
| // Check that value is always smi.
|
| value_check = ICData::New(Function::Handle(),
|
| String::Handle(),
|
| @@ -1746,8 +1650,8 @@
|
| value_check.AddReceiverCheck(kSmiCid, Function::Handle());
|
| break;
|
| }
|
| - case kInt32ArrayCid:
|
| - case kUint32ArrayCid:
|
| + case kTypedDataInt32ArrayCid:
|
| + case kTypedDataUint32ArrayCid:
|
| // We don't have ICData for the value stored, so we optimistically assume
|
| // smis first. If we ever deoptimized here, we require to unbox the value
|
| // before storing to handle the mint case, too.
|
| @@ -1759,8 +1663,8 @@
|
| value_check.AddReceiverCheck(kSmiCid, Function::Handle());
|
| }
|
| break;
|
| - case kFloat32ArrayCid:
|
| - case kFloat64ArrayCid: {
|
| + case kTypedDataFloat32ArrayCid:
|
| + case kTypedDataFloat64ArrayCid: {
|
| // Check that value is always double.
|
| value_check = ICData::New(Function::Handle(),
|
| String::Handle(),
|
| @@ -1775,7 +1679,6 @@
|
| return NULL;
|
| }
|
|
|
| - Definition* array = call->ArgumentAt(0);
|
| Definition* index = call->ArgumentAt(1);
|
| Definition* stored_value = call->ArgumentAt(2);
|
| if (!value_check.IsNull()) {
|
| @@ -1783,20 +1686,6 @@
|
| call);
|
| }
|
| StoreBarrierType needs_store_barrier = kNoStoreBarrier;
|
| -
|
| -
|
| - // result = index + bytesPerElement.
|
| - intptr_t element_size = FlowGraphCompiler::ElementSizeFor(receiver_cid);
|
| - ConstantInstr* bytes_per_element =
|
| - new ConstantInstr(Smi::Handle(Smi::New(element_size)));
|
| - InsertBefore(call, bytes_per_element, NULL, Definition::kValue);
|
| - BinarySmiOpInstr* result =
|
| - new BinarySmiOpInstr(Token::kADD,
|
| - call,
|
| - new Value(index),
|
| - new Value(bytes_per_element));
|
| - InsertBefore(call, result, call->env(), Definition::kValue);
|
| -
|
| StoreIndexedInstr* array_op = new StoreIndexedInstr(new Value(array),
|
| new Value(index),
|
| new Value(stored_value),
|
| @@ -1804,9 +1693,7 @@
|
| 1, // Index scale
|
| view_cid,
|
| call->deopt_id());
|
| - call->ReplaceUsesWith(result); // Fix uses of the call's return value.
|
| ReplaceCall(call, array_op);
|
| - array_op->ClearSSATempIndex(); // Store has no uses.
|
| return true;
|
| }
|
|
|
| @@ -1814,14 +1701,14 @@
|
| void FlowGraphOptimizer::PrepareByteArrayViewOp(
|
| InstanceCallInstr* call,
|
| intptr_t receiver_cid,
|
| - intptr_t view_cid) {
|
| - Definition* array = call->ArgumentAt(0);
|
| + intptr_t view_cid,
|
| + Definition** array) {
|
| Definition* byte_index = call->ArgumentAt(1);
|
|
|
| AddReceiverCheck(call);
|
| const bool is_immutable = true;
|
| LoadFieldInstr* length = new LoadFieldInstr(
|
| - new Value(array),
|
| + new Value(*array),
|
| CheckArrayBoundInstr::LengthOffsetFor(receiver_cid),
|
| Type::ZoneHandle(Type::SmiType()),
|
| is_immutable);
|
| @@ -1850,6 +1737,15 @@
|
| call),
|
| call->env(),
|
| Definition::kEffect);
|
| +
|
| + // Insert load of elements for external typed arrays.
|
| + if (RawObject::IsExternalTypedDataClassId(receiver_cid)) {
|
| + LoadUntaggedInstr* elements =
|
| + new LoadUntaggedInstr(new Value(*array),
|
| + ExternalTypedData::data_offset());
|
| + InsertBefore(call, elements, NULL, Definition::kValue);
|
| + *array = elements;
|
| + }
|
| }
|
|
|
|
|
| @@ -4090,6 +3986,11 @@
|
| }
|
|
|
|
|
| +void ConstantPropagator::VisitLoadUntagged(LoadUntaggedInstr* instr) {
|
| + SetValue(instr, non_constant_);
|
| +}
|
| +
|
| +
|
| void ConstantPropagator::VisitLoadField(LoadFieldInstr* instr) {
|
| if ((instr->recognized_kind() == MethodRecognizer::kObjectArrayLength) &&
|
| (instr->value()->definition()->IsCreateArray())) {
|
|
|