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

Unified Diff: runtime/vm/flow_graph_builder.cc

Issue 15979010: Fix two bugs in the Dart VM's super-noSuchMethod invocation. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 7 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_builder.h ('k') | tests/language/language.status » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/flow_graph_builder.cc
===================================================================
--- runtime/vm/flow_graph_builder.cc (revision 23405)
+++ runtime/vm/flow_graph_builder.cc (working copy)
@@ -1840,8 +1840,10 @@
class TempLocalScope : public ValueObject {
public:
- TempLocalScope(EffectGraphVisitor* visitor, Value* value)
- : visitor_(visitor) {
+ TempLocalScope(EffectGraphVisitor* visitor,
+ Value* value,
+ bool return_definition = true)
srdjan 2013/05/30 17:42:30 WOuld it be better to have a subclass instead of t
Florian Schneider 2013/05/31 08:46:36 I reconsidered using the constructor/destructor of
+ : visitor_(visitor), return_definition_(return_definition) {
ASSERT(value->definition()->temp_index() == visitor->temp_index() - 1);
intptr_t index = visitor->GetCurrentTempLocalIndex();
char name[64];
@@ -1855,15 +1857,25 @@
LocalVariable* var() const { return var_; }
- ~TempLocalScope() {
- Value* result = visitor_->Bind(new LoadLocalInstr(*var_));
+ Value* CloseAndReturnValue() {
+ ASSERT(!return_definition_);
+ Value* tmp = visitor_->Bind(new LoadLocalInstr(*var_));
visitor_->DeallocateTempIndex(1);
- visitor_->ReturnDefinition(new DropTempsInstr(1, result));
+ return visitor_->Bind(new DropTempsInstr(1, tmp));
}
+ ~TempLocalScope() {
+ if (return_definition_) {
+ Value* result = visitor_->Bind(new LoadLocalInstr(*var_));
+ visitor_->DeallocateTempIndex(1);
+ visitor_->ReturnDefinition(new DropTempsInstr(1, result));
+ }
+ }
+
private:
EffectGraphVisitor* visitor_;
LocalVariable* var_;
+ bool return_definition_;
srdjan 2013/05/30 17:42:30 const
Florian Schneider 2013/05/31 08:46:36 Replaced TempLocalScope with EnterScope/ExitScope
};
@@ -2582,10 +2594,12 @@
// Resolve and call noSuchMethod.
ArgumentListNode* arguments = new ArgumentListNode(node->token_pos());
arguments->Add(node->receiver());
- StaticCallInstr* call = BuildStaticNoSuchMethodCall(node->cls(),
- node->receiver(),
- getter_name,
- arguments);
+ StaticCallInstr* call =
+ BuildStaticNoSuchMethodCall(node->cls(),
+ node->receiver(),
+ getter_name,
+ arguments,
+ false); // Don't save last argument.
ReturnDefinition(call);
return;
} else {
@@ -2656,10 +2670,12 @@
ArgumentListNode* arguments = new ArgumentListNode(node->token_pos());
arguments->Add(node->receiver());
arguments->Add(node->value());
- call = BuildStaticNoSuchMethodCall(node->cls(),
- node->receiver(),
- setter_name,
- arguments);
+ call = BuildStaticNoSuchMethodCall(
+ node->cls(),
+ node->receiver(),
+ setter_name,
+ arguments,
+ result_is_needed); // Save last arg if result is needed.
} else {
// Throw a NoSuchMethodError.
call = BuildThrowNoSuchMethodError(
@@ -2891,7 +2907,8 @@
BuildStaticNoSuchMethodCall(node->super_class(),
node->array(),
Symbols::IndexToken(),
- arguments);
+ arguments,
+ false); // Don't save last arg.
ReturnDefinition(call);
return;
}
@@ -2945,29 +2962,16 @@
ArgumentListNode* arguments = new ArgumentListNode(node->token_pos());
arguments->Add(node->array());
arguments->Add(node->index_expr());
-
- // Even though noSuchMethod most likely does not return,
- // we save the stored value if the result is needed.
+ arguments->Add(node->value());
+ StaticCallInstr* call = BuildStaticNoSuchMethodCall(
+ node->super_class(),
+ node->array(),
+ Symbols::AssignIndexToken(),
+ arguments,
+ result_is_needed); // Save last arg if result is needed.
if (result_is_needed) {
- ValueGraphVisitor for_value(owner(), temp_index());
- node->value()->Visit(&for_value);
- Append(for_value);
- Do(BuildStoreExprTemp(for_value.value()));
-
- const LocalVariable* temp =
- owner()->parsed_function().expression_temp_var();
- AstNode* value = new LoadLocalNode(node->token_pos(), temp);
- arguments->Add(value);
- } else {
- arguments->Add(node->value());
- }
- StaticCallInstr* call =
- BuildStaticNoSuchMethodCall(node->super_class(),
- node->array(),
- Symbols::AssignIndexToken(),
- arguments);
- if (result_is_needed) {
Do(call);
+ // BuildStaticNoSuchMethodCall stores the value in expression_temp.
return BuildLoadExprTemp();
} else {
return call;
@@ -3317,7 +3321,8 @@
const Class& target_class,
AstNode* receiver,
const String& method_name,
- ArgumentListNode* method_arguments) {
+ ArgumentListNode* method_arguments,
+ bool save_last_arg) {
// Build the graph to allocate an InvocationMirror object by calling
// the static allocation method.
const Library& corelib = Library::Handle(Library::CoreLibrary());
@@ -3340,27 +3345,60 @@
// Allocate the arguments and pass them into the construction
// of the InvocationMirror.
- const intptr_t args_pos = method_arguments->token_pos();
- ArgumentListNode* arguments = new ArgumentListNode(args_pos);
+ ZoneGrowableArray<PushArgumentInstr*>* allocation_args =
+ new ZoneGrowableArray<PushArgumentInstr*>(3);
// The first argument is the original method name.
- arguments->Add(new LiteralNode(args_pos, method_name));
+ allocation_args->Add(PushArgument(Bind(new ConstantInstr(method_name))));
+
// The second argument is the arguments descriptor of the original method.
const Array& args_descriptor =
Array::ZoneHandle(ArgumentsDescriptor::New(method_arguments->length(),
method_arguments->names()));
- arguments->Add(new LiteralNode(args_pos, args_descriptor));
+ allocation_args->Add(PushArgument(Bind(new ConstantInstr(args_descriptor))));
+
// The third argument is an array containing the original method arguments,
// including the receiver.
- ArrayNode* args_array = new ArrayNode(
- args_pos,
- Type::ZoneHandle(Type::ArrayType()));
- for (intptr_t i = 0; i < method_arguments->length(); i++) {
- args_array->AddElement(method_arguments->NodeAt(i));
+ intptr_t args_pos = method_arguments->token_pos();
+ Value* element_type =
+ Bind(new ConstantInstr(AbstractTypeArguments::ZoneHandle()));
+ CreateArrayInstr* create =
+ new CreateArrayInstr(args_pos,
+ method_arguments->length(),
+ Type::ZoneHandle(Type::ArrayType()),
+ element_type);
+ Value* args_array = Bind(create);
+ { TempLocalScope tmp(this,
+ args_array,
+ false); // Don't pass value to the visitor.
+ const intptr_t class_id = create->Type()->ToCid();
+ const intptr_t deopt_id = Isolate::kNoDeoptId;
+ for (int i = 0; i < method_arguments->length(); ++i) {
+ Value* array = Bind(new LoadLocalInstr(*tmp.var()));
+ Value* index = Bind(new ConstantInstr(Smi::ZoneHandle(Smi::New(i))));
+ ValueGraphVisitor for_value(owner(), temp_index());
+ method_arguments->NodeAt(i)->Visit(&for_value);
+ Append(for_value);
+ Value* value = for_value.value();
+ if (save_last_arg && i == method_arguments->length() - 1) {
srdjan 2013/05/30 17:42:30 Add parenthesis.
Florian Schneider 2013/05/31 08:51:19 Done.
+ // We can use the expression_temp_var here because this is always the
+ // last argument before the call.
+ value = Bind(BuildStoreExprTemp(value));
+ }
+ // No store barrier needed for constants.
+ const StoreBarrierType emit_store_barrier =
+ value->BindsToConstant()
+ ? kNoStoreBarrier
+ : kEmitStoreBarrier;
+ intptr_t index_scale = FlowGraphCompiler::ElementSizeFor(class_id);
+ StoreIndexedInstr* store = new StoreIndexedInstr(
+ array, index, value,
+ emit_store_barrier, index_scale, class_id, deopt_id);
+ Do(store);
+ }
+ args_array = tmp.CloseAndReturnValue();
}
- arguments->Add(args_array);
- ZoneGrowableArray<PushArgumentInstr*>* allocation_args =
- new ZoneGrowableArray<PushArgumentInstr*>(arguments->length());
- BuildPushArguments(*arguments, allocation_args);
+ allocation_args->Add(PushArgument(args_array));
+
StaticCallInstr* allocation = new StaticCallInstr(args_pos,
allocation_function,
Array::ZoneHandle(),
« no previous file with comments | « runtime/vm/flow_graph_builder.h ('k') | tests/language/language.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698