Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(683)

Unified Diff: runtime/vm/flow_graph_optimizer.cc

Issue 11092090: Inline indexed load and store of typed array float64. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/flow_graph_optimizer.h ('k') | runtime/vm/intermediate_language.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/flow_graph_optimizer.cc
===================================================================
--- runtime/vm/flow_graph_optimizer.cc (revision 13666)
+++ runtime/vm/flow_graph_optimizer.cc (working copy)
@@ -374,79 +374,126 @@
}
-bool FlowGraphOptimizer::TryReplaceWithArrayOp(InstanceCallInstr* call,
- Token::Kind op_kind) {
+// Returns array classid to load from, array and idnex value
+
+intptr_t FlowGraphOptimizer::PrepareIndexedOp(InstanceCallInstr* call,
+ intptr_t class_id,
+ Value** array,
+ Value** index) {
+ *array = call->ArgumentAt(0)->value();
+ *index = call->ArgumentAt(1)->value();
+ // Insert class check and index smi checks and attach a copy of the
+ // original environment because the operation can still deoptimize.
+ AddCheckClass(call, (*array)->Copy());
+ InsertBefore(call,
+ new CheckSmiInstr((*index)->Copy(), call->deopt_id()),
+ call->env(),
+ Definition::kEffect);
+ // If both index and array are constants, then the bound check always
+ // succeeded.
+ // TODO(srdjan): Remove once constant propagation lands.
+ if (!((*array)->BindsToConstant() && (*index)->BindsToConstant())) {
+ // Insert array bounds check.
+ InsertBefore(call,
+ new CheckArrayBoundInstr((*array)->Copy(),
+ (*index)->Copy(),
+ class_id,
+ call),
+ call->env(),
+ Definition::kEffect);
+ }
+ if (class_id == kGrowableObjectArrayCid) {
+ // Insert data elements load.
+ LoadFieldInstr* elements =
+ new LoadFieldInstr((*array)->Copy(),
+ GrowableObjectArray::data_offset(),
+ Type::ZoneHandle(Type::DynamicType()));
+ elements->set_result_cid(kArrayCid);
+ InsertBefore(call, elements, NULL, Definition::kValue);
+ *array = new Value(elements);
+ return kArrayCid;
+ }
+ return class_id;
+}
+
+
+bool FlowGraphOptimizer::TryReplaceWithStoreIndexed(InstanceCallInstr* call) {
// TODO(fschneider): Optimize []= operator in checked mode as well.
- if (op_kind == Token::kASSIGN_INDEX && FLAG_enable_type_checks) return false;
-
+ if (FLAG_enable_type_checks) return false;
const intptr_t class_id = ReceiverClassId(call);
+ ICData& value_check = ICData::Handle();
switch (class_id) {
- case kImmutableArrayCid:
- // Stores are only specialized for Array and GrowableObjectArray,
- // not for ImmutableArray.
- if (op_kind == Token::kASSIGN_INDEX) return false;
- // Fall through.
case kArrayCid:
- case kGrowableObjectArrayCid: {
- Value* array = call->ArgumentAt(0)->value();
- Value* index = call->ArgumentAt(1)->value();
- // Insert class check and index smi checks and attach a copy of the
- // original environment because the operation can still deoptimize.
- AddCheckClass(call, array->Copy());
- InsertBefore(call,
- new CheckSmiInstr(index->Copy(), call->deopt_id()),
- call->env(),
- Definition::kEffect);
- // If both index and array are constants, then the bound check always
- // succeeded.
- // TODO(srdjan): Remove once constant propagation lands.
- if (!(array->BindsToConstant() && index->BindsToConstant())) {
- // Insert array bounds check.
- InsertBefore(call,
- new CheckArrayBoundInstr(array->Copy(),
- index->Copy(),
- class_id,
- call),
- call->env(),
- Definition::kEffect);
+ case kGrowableObjectArrayCid:
+ // Acceptable store index classes.
+ break;
+ case kFloat64ArrayCid: {
+ // Check that value is always double.
+ value_check = call->ic_data()->AsUnaryClassChecksForArgNr(2);
+ if ((value_check.NumberOfChecks() != 1) ||
+ (value_check.GetReceiverClassIdAt(0) != kDoubleCid)) {
+ return false;
}
- if (class_id == kGrowableObjectArrayCid) {
- // Insert data elements load.
- LoadFieldInstr* elements =
- new LoadFieldInstr(array->Copy(),
- GrowableObjectArray::data_offset(),
- Type::ZoneHandle(Type::DynamicType()));
- elements->set_result_cid(kArrayCid);
- InsertBefore(call, elements, NULL, Definition::kValue);
- array = new Value(elements);
- }
- Definition* array_op = NULL;
- if (op_kind == Token::kINDEX) {
- array_op = new LoadIndexedInstr(array, index);
- } else {
- bool needs_store_barrier = true;
- if (ArgIsAlwaysSmi(*call->ic_data(), 2)) {
- InsertBefore(call,
- new CheckSmiInstr(call->ArgumentAt(2)->value()->Copy(),
- call->deopt_id()),
- call->env(),
- Definition::kEffect);
- needs_store_barrier = false;
- }
- Value* value = call->ArgumentAt(2)->value();
- array_op =
- new StoreIndexedInstr(array, index, value, needs_store_barrier);
- }
- call->ReplaceWith(array_op, current_iterator());
- RemovePushArguments(call);
- return true;
+ break;
}
default:
return false;
}
+ Value* array = NULL;
+ Value* index = NULL;
+ intptr_t array_cid = PrepareIndexedOp(call, class_id, &array, &index);
+ Value* value = call->ArgumentAt(2)->value();
+ // Check if store barrier is needed.
+ bool needs_store_barrier = true;
+ if (class_id == kFloat64ArrayCid) {
+ ASSERT(!value_check.IsNull());
+ InsertBefore(call,
+ new CheckClassInstr(value->Copy(),
+ call->deopt_id(),
+ value_check),
+ call->env(),
+ Definition::kEffect);
+ needs_store_barrier = false;
+ } else if (ArgIsAlwaysSmi(*call->ic_data(), 2)) {
+ InsertBefore(call,
+ new CheckSmiInstr(value->Copy(), call->deopt_id()),
+ call->env(),
+ Definition::kEffect);
+ needs_store_barrier = false;
+ }
+
+ Definition* array_op =
+ new StoreIndexedInstr(array, index, value,
+ needs_store_barrier, array_cid, call->deopt_id());
+ call->ReplaceWith(array_op, current_iterator());
+ RemovePushArguments(call);
+ return true;
}
+
+bool FlowGraphOptimizer::TryReplaceWithLoadIndexed(InstanceCallInstr* call) {
+ const intptr_t class_id = ReceiverClassId(call);
+ switch (class_id) {
+ case kArrayCid:
+ case kImmutableArrayCid:
+ case kGrowableObjectArrayCid:
+ case kFloat64ArrayCid:
+ // Acceptable load index classes.
+ break;
+ default:
+ return false;
+ }
+ Value* array = NULL;
+ Value* index = NULL;
+ intptr_t array_cid = PrepareIndexedOp(call, class_id, &array, &index);
+ Definition* array_op = new LoadIndexedInstr(array, index, array_cid);
+ call->ReplaceWith(array_op, current_iterator());
+ RemovePushArguments(call);
+ return true;
+}
+
+
void FlowGraphOptimizer::InsertBefore(Instruction* next,
Instruction* instr,
Environment* env,
@@ -960,10 +1007,13 @@
void FlowGraphOptimizer::VisitInstanceCall(InstanceCallInstr* instr) {
if (instr->HasICData() && (instr->ic_data()->NumberOfChecks() > 0)) {
const Token::Kind op_kind = instr->token_kind();
- if (Token::IsIndexOperator(op_kind) &&
- TryReplaceWithArrayOp(instr, op_kind)) {
+ if ((op_kind == Token::kASSIGN_INDEX) &&
+ TryReplaceWithStoreIndexed(instr)) {
return;
}
+ if ((op_kind == Token::kINDEX) && TryReplaceWithLoadIndexed(instr)) {
+ return;
+ }
if (Token::IsBinaryToken(op_kind) &&
TryReplaceWithBinaryOp(instr, op_kind)) {
return;
« no previous file with comments | « runtime/vm/flow_graph_optimizer.h ('k') | runtime/vm/intermediate_language.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698