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

Unified Diff: runtime/vm/flow_graph_builder.cc

Issue 1180903002: null-aware operators in the VM (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Add test for opt compiler Created 5 years, 6 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
Index: runtime/vm/flow_graph_builder.cc
diff --git a/runtime/vm/flow_graph_builder.cc b/runtime/vm/flow_graph_builder.cc
index a90c9faa09c61c788dd5ff2d4c6519d563ed6deb..2f98cfc779350ab0180d947fa380644b2e1926be 100644
--- a/runtime/vm/flow_graph_builder.cc
+++ b/runtime/vm/flow_graph_builder.cc
@@ -1335,6 +1335,36 @@ void EffectGraphVisitor::VisitBinaryOpNode(BinaryOpNode* node) {
}
}
return;
+ } else if (node->kind() == Token::kIFNULL) {
+ // left ?? right. This operation cannot be overloaded.
+ // temp = left; temp === null ? right : temp
+ ValueGraphVisitor for_left_value(owner());
+ node->left()->Visit(&for_left_value);
+ Append(for_left_value);
+ Do(BuildStoreExprTemp(for_left_value.value()));
+
+ LocalVariable* temp_var = owner()->parsed_function().expression_temp_var();
+ LoadLocalNode* load_temp =
+ new(Z) LoadLocalNode(Scanner::kNoSourcePos, temp_var);
+ LiteralNode* null_constant =
+ new(Z) LiteralNode(Scanner::kNoSourcePos, Object::null_instance());
+ ComparisonNode* check_is_null =
+ new(Z) ComparisonNode(Scanner::kNoSourcePos,
+ Token::kEQ_STRICT,
+ load_temp,
+ null_constant);
+ TestGraphVisitor for_test(owner(), Scanner::kNoSourcePos);
+ check_is_null->Visit(&for_test);
+
+ ValueGraphVisitor for_right_value(owner());
+ node->right()->Visit(&for_right_value);
+ for_right_value.Do(BuildStoreExprTemp(for_right_value.value()));
+
+ ValueGraphVisitor for_temp(owner());
+ // Nothing to do, left value is already loaded into temp.
+
+ Join(for_test, for_right_value, for_temp);
+ return;
}
ValueGraphVisitor for_left_value(owner());
node->left()->Visit(&for_left_value);
@@ -1410,7 +1440,39 @@ void ValueGraphVisitor::VisitBinaryOpNode(BinaryOpNode* node) {
}
ReturnDefinition(BuildLoadExprTemp());
return;
+ } else if (node->kind() == Token::kIFNULL) {
+ // left ?? right. This operation cannot be overloaded.
+ // temp = left; temp === null ? right : temp
Florian Schneider 2015/06/18 14:09:00 Is this the same code as in EffectGraphVisitor::Vi
hausner 2015/06/18 17:55:37 There is some duplication here that I would like t
+ ValueGraphVisitor for_left_value(owner());
+ node->left()->Visit(&for_left_value);
+ Append(for_left_value);
+ Do(BuildStoreExprTemp(for_left_value.value()));
+
+ LocalVariable* temp_var = owner()->parsed_function().expression_temp_var();
+ LoadLocalNode* load_temp =
+ new(Z) LoadLocalNode(Scanner::kNoSourcePos, temp_var);
+ LiteralNode* null_constant =
+ new(Z) LiteralNode(Scanner::kNoSourcePos, Object::null_instance());
+ ComparisonNode* check_is_null =
+ new(Z) ComparisonNode(Scanner::kNoSourcePos,
+ Token::kEQ_STRICT,
+ load_temp,
+ null_constant);
+ TestGraphVisitor for_test(owner(), Scanner::kNoSourcePos);
+ check_is_null->Visit(&for_test);
+
+ ValueGraphVisitor for_right_value(owner());
+ node->right()->Visit(&for_right_value);
+ for_right_value.Do(BuildStoreExprTemp(for_right_value.value()));
+
+ ValueGraphVisitor for_temp(owner());
+ // Nothing to do, left value is already loaded into temp.
+
+ Join(for_test, for_right_value, for_temp);
+ ReturnDefinition(BuildLoadExprTemp());
+ return;
}
+
EffectGraphVisitor::VisitBinaryOpNode(node);
}
@@ -2703,22 +2765,58 @@ void EffectGraphVisitor::VisitInstanceCallNode(InstanceCallNode* node) {
ValueGraphVisitor for_receiver(owner());
node->receiver()->Visit(&for_receiver);
Append(for_receiver);
- PushArgumentInstr* push_receiver = PushArgument(for_receiver.value());
- ZoneGrowableArray<PushArgumentInstr*>* arguments =
- new(Z) ZoneGrowableArray<PushArgumentInstr*>(
- node->arguments()->length() + 1);
- arguments->Add(push_receiver);
+ if (node->is_conditional()) {
+ Do(BuildStoreExprTemp(for_receiver.value()));
+ LocalVariable* temp_var = owner()->parsed_function().expression_temp_var();
+ LoadLocalNode* load_temp =
+ new(Z) LoadLocalNode(Scanner::kNoSourcePos, temp_var);
+
+ LiteralNode* null_constant =
+ new(Z) LiteralNode(Scanner::kNoSourcePos, Object::null_instance());
+ ComparisonNode* check_is_null =
+ new(Z) ComparisonNode(Scanner::kNoSourcePos,
+ Token::kEQ,
+ load_temp,
+ null_constant);
+ TestGraphVisitor for_test(owner(), Scanner::kNoSourcePos);
+ check_is_null->Visit(&for_test);
+
+ EffectGraphVisitor for_true(owner());
+ EffectGraphVisitor for_false(owner());
+
+ StoreLocalNode* store_null =
+ new(Z) StoreLocalNode(Scanner::kNoSourcePos, temp_var, null_constant);
+ store_null->Visit(&for_true);
+
+ InstanceCallNode* call =
+ new(Z) InstanceCallNode(node->token_pos(),
+ load_temp,
+ node->function_name(),
+ node->arguments());
+ StoreLocalNode* store_result =
+ new(Z) StoreLocalNode(Scanner::kNoSourcePos, temp_var, call);
+ store_result->Visit(&for_false);
+
+ Join(for_test, for_true, for_false);
+ ReturnDefinition(BuildLoadExprTemp());
+ } else {
+ PushArgumentInstr* push_receiver = PushArgument(for_receiver.value());
+ ZoneGrowableArray<PushArgumentInstr*>* arguments =
+ new(Z) ZoneGrowableArray<PushArgumentInstr*>(
+ node->arguments()->length() + 1);
+ arguments->Add(push_receiver);
- BuildPushArguments(*node->arguments(), arguments);
- InstanceCallInstr* call = new(Z) InstanceCallInstr(
- node->token_pos(),
- node->function_name(),
- Token::kILLEGAL,
- arguments,
- node->arguments()->names(),
- 1,
- owner()->ic_data_array());
- ReturnDefinition(call);
+ BuildPushArguments(*node->arguments(), arguments);
+ InstanceCallInstr* call = new(Z) InstanceCallInstr(
+ node->token_pos(),
+ node->function_name(),
+ Token::kILLEGAL,
+ arguments,
+ node->arguments()->names(),
+ 1,
+ owner()->ic_data_array());
+ ReturnDefinition(call);
+ }
}
@@ -3063,20 +3161,55 @@ void EffectGraphVisitor::VisitInstanceGetterNode(InstanceGetterNode* node) {
ValueGraphVisitor for_receiver(owner());
node->receiver()->Visit(&for_receiver);
Append(for_receiver);
- PushArgumentInstr* push_receiver = PushArgument(for_receiver.value());
- ZoneGrowableArray<PushArgumentInstr*>* arguments =
- new(Z) ZoneGrowableArray<PushArgumentInstr*>(1);
- arguments->Add(push_receiver);
- const String& name =
- String::ZoneHandle(Z, Field::GetterSymbol(node->field_name()));
- InstanceCallInstr* call = new(Z) InstanceCallInstr(
- node->token_pos(),
- name,
- Token::kGET,
- arguments, Object::null_array(),
- 1,
- owner()->ic_data_array());
- ReturnDefinition(call);
+ if (node->is_conditional()) {
+ Do(BuildStoreExprTemp(for_receiver.value()));
+ LocalVariable* temp_var = owner()->parsed_function().expression_temp_var();
+ LoadLocalNode* load_temp =
+ new(Z) LoadLocalNode(Scanner::kNoSourcePos, temp_var);
+
+ LiteralNode* null_constant =
+ new(Z) LiteralNode(Scanner::kNoSourcePos, Object::null_instance());
+ ComparisonNode* check_is_null =
+ new(Z) ComparisonNode(Scanner::kNoSourcePos,
+ Token::kEQ,
+ load_temp,
+ null_constant);
+ TestGraphVisitor for_test(owner(), Scanner::kNoSourcePos);
+ check_is_null->Visit(&for_test);
+
+ EffectGraphVisitor for_true(owner());
+ EffectGraphVisitor for_false(owner());
+
+ StoreLocalNode* store_null =
+ new(Z) StoreLocalNode(Scanner::kNoSourcePos, temp_var, null_constant);
+ store_null->Visit(&for_true);
+
+ InstanceGetterNode* getter =
+ new(Z) InstanceGetterNode(node->token_pos(),
+ load_temp,
+ node->field_name());
+ StoreLocalNode* store_getter =
+ new(Z) StoreLocalNode(Scanner::kNoSourcePos, temp_var, getter);
+ store_getter->Visit(&for_false);
+
+ Join(for_test, for_true, for_false);
+ ReturnDefinition(BuildLoadExprTemp());
+ } else {
+ PushArgumentInstr* push_receiver = PushArgument(for_receiver.value());
+ ZoneGrowableArray<PushArgumentInstr*>* arguments =
+ new(Z) ZoneGrowableArray<PushArgumentInstr*>(1);
+ arguments->Add(push_receiver);
+ const String& name =
+ String::ZoneHandle(Z, Field::GetterSymbol(node->field_name()));
+ InstanceCallInstr* call = new(Z) InstanceCallInstr(
+ node->token_pos(),
+ name,
+ Token::kGET,
+ arguments, Object::null_array(),
+ 1,
+ owner()->ic_data_array());
+ ReturnDefinition(call);
+ }
}
@@ -3104,6 +3237,37 @@ void EffectGraphVisitor::BuildInstanceSetterArguments(
void EffectGraphVisitor::VisitInstanceSetterNode(InstanceSetterNode* node) {
+ if (node->is_conditional()) {
+ ValueGraphVisitor for_receiver(owner());
+ node->receiver()->Visit(&for_receiver);
+ Append(for_receiver);
+ Do(BuildStoreExprTemp(for_receiver.value()));
+
+ LocalVariable* temp_var = owner()->parsed_function().expression_temp_var();
+ LoadLocalNode* load_temp =
+ new(Z) LoadLocalNode(Scanner::kNoSourcePos, temp_var);
+ LiteralNode* null_constant =
+ new(Z) LiteralNode(Scanner::kNoSourcePos, Object::null_instance());
+ ComparisonNode* check_is_null =
+ new(Z) ComparisonNode(Scanner::kNoSourcePos,
+ Token::kEQ,
+ load_temp,
+ null_constant);
+ TestGraphVisitor for_test(owner(), Scanner::kNoSourcePos);
+ check_is_null->Visit(&for_test);
+
+ EffectGraphVisitor for_true(owner());
+ EffectGraphVisitor for_false(owner());
+
+ InstanceSetterNode* setter =
+ new(Z) InstanceSetterNode(node->token_pos(),
+ load_temp,
+ node->field_name(),
+ node->value());
+ setter->Visit(&for_false);
+ Join(for_test, for_true, for_false);
+ return;
+ }
ZoneGrowableArray<PushArgumentInstr*>* arguments =
new(Z) ZoneGrowableArray<PushArgumentInstr*>(2);
BuildInstanceSetterArguments(node, arguments, kResultNotNeeded);
@@ -3122,6 +3286,42 @@ void EffectGraphVisitor::VisitInstanceSetterNode(InstanceSetterNode* node) {
void ValueGraphVisitor::VisitInstanceSetterNode(InstanceSetterNode* node) {
+ if (node->is_conditional()) {
+ ValueGraphVisitor for_receiver(owner());
+ node->receiver()->Visit(&for_receiver);
+ Append(for_receiver);
+ Do(BuildStoreExprTemp(for_receiver.value()));
+
+ LocalVariable* temp_var = owner()->parsed_function().expression_temp_var();
+ LoadLocalNode* load_temp =
+ new(Z) LoadLocalNode(Scanner::kNoSourcePos, temp_var);
+ LiteralNode* null_constant =
+ new(Z) LiteralNode(Scanner::kNoSourcePos, Object::null_instance());
+ ComparisonNode* check_is_null =
+ new(Z) ComparisonNode(Scanner::kNoSourcePos,
+ Token::kEQ,
+ load_temp,
+ null_constant);
+ TestGraphVisitor for_test(owner(), Scanner::kNoSourcePos);
+ check_is_null->Visit(&for_test);
+
+ ValueGraphVisitor for_true(owner());
+ null_constant->Visit(&for_true);
+ for_true.Do(BuildStoreExprTemp(for_true.value()));
+
+ ValueGraphVisitor for_false(owner());
+ InstanceSetterNode* setter =
+ new(Z) InstanceSetterNode(node->token_pos(),
+ load_temp,
+ node->field_name(),
+ node->value());
+ setter->Visit(&for_false);
+ for_false.Do(BuildStoreExprTemp(for_false.value()));
+
+ Join(for_test, for_true, for_false);
+ ReturnDefinition(BuildLoadExprTemp());
+ return;
+ }
ZoneGrowableArray<PushArgumentInstr*>* arguments =
new(Z) ZoneGrowableArray<PushArgumentInstr*>(2);
BuildInstanceSetterArguments(node, arguments, kResultNeeded);
« runtime/vm/ast.h ('K') | « runtime/vm/ast_transformer.cc ('k') | runtime/vm/parser.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698