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

Unified Diff: runtime/vm/flow_graph_builder.cc

Issue 9726024: Add contexts. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 9 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
===================================================================
--- runtime/vm/flow_graph_builder.cc (revision 5781)
+++ runtime/vm/flow_graph_builder.cc (working copy)
@@ -166,6 +166,23 @@
}
}
+ intptr_t current_context_level = owner()->context_level();
+ ASSERT(current_context_level >= 0);
+ if (owner()->parsed_function().saved_context_var() != NULL) {
+ // CTX on entry was saved, but not linked as context parent.
+ LoadLocalComp* load_comp =
+ new LoadLocalComp(*owner()->parsed_function().saved_context_var(), 0);
+ AddInstruction(new BindInstr(temp_index(), load_comp));
+ TempVal* local_value = new TempVal(temp_index());
+ StoreContextComp* store_context = new StoreContextComp(local_value);
+ AddInstruction(new DoInstr(store_context));
+ } else {
+ while (current_context_level-- > 0) {
+ UnchainContext();
+ }
+ }
+
+
AddInstruction(new ReturnInstr(return_value, node->token_index()));
CloseFragment();
}
@@ -387,14 +404,15 @@
// because its value is not needed.
// 1. Load the value.
- LoadLocalComp* load = new LoadLocalComp(node->local());
+ LoadLocalComp* load = new LoadLocalComp(node->local(),
+ owner()->context_level());
AddInstruction(new BindInstr(temp_index(), load));
// 2. Increment.
BuildIncrOpIncrement(node->kind(), node->id(), node->token_index(),
temp_index() + 1);
// 3. Perform the store, resulting in the new value.
- StoreLocalComp* store =
- new StoreLocalComp(node->local(), new TempVal(temp_index()));
+ StoreLocalComp* store = new StoreLocalComp(
+ node->local(), new TempVal(temp_index()), owner()->context_level());
ReturnComputation(store);
}
@@ -410,7 +428,8 @@
// result.
//
// 1. Load the value.
- LoadLocalComp* load = new LoadLocalComp(node->local());
+ LoadLocalComp* load = new LoadLocalComp(node->local(),
+ owner()->context_level());
AddInstruction(new BindInstr(temp_index(), load));
// 2. Duplicate it to increment.
AddInstruction(new PickTempInstr(temp_index() + 1, temp_index()));
@@ -418,8 +437,8 @@
BuildIncrOpIncrement(node->kind(), node->id(), node->token_index(),
temp_index() + 2);
// 4. Perform the store and return the original value.
- StoreLocalComp* store =
- new StoreLocalComp(node->local(), new TempVal(temp_index() + 1));
+ StoreLocalComp* store = new StoreLocalComp(
+ node->local(), new TempVal(temp_index() + 1), owner()->context_level());
AddInstruction(new DoInstr(store));
ReturnValue(new TempVal(AllocateTempIndex()));
}
@@ -725,7 +744,8 @@
TargetEntryInstr* back_target_entry = new TargetEntryInstr();
*for_test.true_successor_address() = back_target_entry;
back_target_entry->SetSuccessor(join);
- exit_ = *for_test.false_successor_address() = new TargetEntryInstr();
+ exit_ =
+ *for_test.false_successor_address() = new TargetEntryInstr();
}
@@ -800,9 +820,8 @@
int next_index = temp_index();
if (function.IsNonImplicitClosureFunction()) {
- const int context_level = 0; // Only because we don't handle nesting yet.
const ContextScope& context_scope = ContextScope::ZoneHandle(
- node->scope()->PreserveOuterScope(context_level));
+ node->scope()->PreserveOuterScope(owner()->context_level()));
ASSERT(!function.HasCode());
ASSERT(function.context_scope() == ContextScope::null());
function.set_context_scope(context_scope);
@@ -1156,13 +1175,17 @@
return;
}
+
void ValueGraphVisitor::VisitLoadLocalNode(LoadLocalNode* node) {
- LoadLocalComp* load = new LoadLocalComp(node->local());
+ LoadLocalComp* load = new LoadLocalComp(node->local(),
+ owner()->context_level());
ReturnComputation(load);
}
+
void TestGraphVisitor::VisitLoadLocalNode(LoadLocalNode* node) {
- LoadLocalComp* load = new LoadLocalComp(node->local());
+ LoadLocalComp* load = new LoadLocalComp(node->local(),
+ owner()->context_level());
ReturnComputation(load);
}
@@ -1182,7 +1205,8 @@
value = new TempVal(temp_index());
}
- StoreLocalComp* store = new StoreLocalComp(node->local(), value);
+ StoreLocalComp* store =
+ new StoreLocalComp(node->local(), value, owner()->context_level());
ReturnComputation(store);
}
@@ -1280,6 +1304,23 @@
}
+bool EffectGraphVisitor::MustSaveRestoreContext(SequenceNode* node) const {
+ return (node == owner()->parsed_function().node_sequence()) &&
+ (owner()->parsed_function().saved_context_var() != NULL);
+}
+
+
+void EffectGraphVisitor::UnchainContext() {
+ AddInstruction(new BindInstr(temp_index(), new CurrentContextComp()));
+ TempVal* temp_ctx = new TempVal(temp_index());
+ NativeLoadFieldComp* load = new NativeLoadFieldComp(
+ temp_ctx, Context::parent_offset());
+ AddInstruction(new BindInstr(temp_index(), load));
+ TempVal* parent_ctx = new TempVal(temp_index());
+ AddInstruction(new DoInstr(new StoreContextComp(parent_ctx)));
+}
+
+
// <Statement> ::= Sequence { scope: LocalScope
// nodes: <Statement>*
// label: SourceLabel }
@@ -1291,9 +1332,76 @@
if (num_context_variables > 0) {
// The loop local scope declares variables that are captured.
// Allocate and chain a new context.
- // Allocate context computation.
- // Chain Context computation (maybe introduce a new variable).
- Bailout("Sequence needs a context. Gotta have a context.");
+ // Allocate context computation (uses current CTX)
+ AllocateContextComp* comp = new AllocateContextComp(node->token_index(),
+ num_context_variables);
+ AddInstruction(new BindInstr(temp_index(), comp));
+ Value* allocated_context_value = new TempVal(temp_index());
+
+ // If this node_sequence is the body of the function being compiled, and if
+ // this function is not a closure, do not link the current context as the
+ // parent of the newly allocated context, as it is not accessible. Instead,
+ // save it in a pre-allocated variable and restore it on exit.
+ if (MustSaveRestoreContext(node)) {
+ AddInstruction(new BindInstr(temp_index() + 1, new CurrentContextComp()));
+ StoreLocalComp* store_local = new StoreLocalComp(
+ *owner()->parsed_function().saved_context_var(),
+ new TempVal(temp_index() + 1),
+ 0);
+ AddInstruction(new DoInstr(store_local));
+ StoreContextComp* store_context =
+ new StoreContextComp(new ConstantVal(Object::ZoneHandle()));
+ AddInstruction(new DoInstr(store_context));
+ }
+
+ ChainContextComp* chain_context = new ChainContextComp(
+ allocated_context_value);
+ AddInstruction(new DoInstr(chain_context));
+ owner()->set_context_level(scope->context_level());
+
+ // If this node_sequence is the body of the function being compiled, copy
+ // the captured parameters from the frame into the context.
+ if (node == owner()->parsed_function().node_sequence()) {
+ ASSERT(scope->context_level() == 1);
+ const Immediate raw_null =
+ Immediate(reinterpret_cast<intptr_t>(Object::null()));
+ const Function& function = owner()->parsed_function().function();
+ const int num_params = function.NumberOfParameters();
+ int param_frame_index =
+ (num_params == function.num_fixed_parameters()) ? 1 + num_params : -1;
+ for (int pos = 0; pos < num_params; param_frame_index--, pos++) {
+ const LocalVariable& parameter = *scope->VariableAt(pos);
+ ASSERT(parameter.owner() == scope);
+ if (parameter.is_captured()) {
+ // Create a temporary local describing the original position.
+ const String& temp_name = String::ZoneHandle(String::Concat(
+ parameter.name(), String::Handle(String::NewSymbol("-orig"))));
+ LocalVariable* temp_local = new LocalVariable(
+ 0, // Token index.
+ temp_name,
+ Type::ZoneHandle(Type::DynamicType())); // Type.
+ temp_local->set_index(param_frame_index);
+
+ // Copy parameter from local frame to current context.
+ LoadLocalComp* load_comp = new LoadLocalComp(
+ *temp_local, owner()->context_level());
+ AddInstruction(new BindInstr(temp_index(), load_comp));
+ StoreLocalComp* store_local = new StoreLocalComp(
+ parameter,
+ new TempVal(temp_index()),
+ owner()->context_level());
+ AddInstruction(new DoInstr(store_local));
+ // Write NULL to the source location to detect buggy accesses and
+ // allow GC of passed value if it gets overwritten by a new value in
+ // the function.
+ StoreLocalComp* clear_local = new StoreLocalComp(
+ *temp_local,
+ new ConstantVal(Object::ZoneHandle()),
+ owner()->context_level());
+ AddInstruction(new DoInstr(clear_local));
+ }
+ }
+ }
}
if (FLAG_enable_type_checks &&
@@ -1307,6 +1415,27 @@
node->NodeAt(i++)->Visit(&for_effect);
Append(for_effect);
}
+
+ if (is_open()) {
+ if (MustSaveRestoreContext(node)) {
+ ASSERT(num_context_variables > 0);
+ LoadLocalComp* load_comp =
+ new LoadLocalComp(*owner()->parsed_function().saved_context_var(), 0);
+ AddInstruction(new BindInstr(temp_index(), load_comp));
+ TempVal* local_value = new TempVal(temp_index());
+ StoreContextComp* store_context = new StoreContextComp(local_value);
+ AddInstruction(new DoInstr(store_context));
+ } else if (num_context_variables > 0) {
+ UnchainContext();
+ }
+ }
+
+ // If this node sequence is labeled, a break out of the sequence will have
+ // taken care of unchaining the context.
+ if (node->label() != NULL) {
+ // TODO(srdjan): Check that the break label is bound? Is this a jump?
+ Bailout("VisitSequenceNode bind break and unchain CTX");
+ }
owner()->set_context_level(previous_context_level);
}
@@ -1474,14 +1603,15 @@
void FlowGraphPrinter::VisitLoadLocal(LoadLocalComp* comp) {
- OS::Print("LoadLocal(%s)", comp->local().name().ToCString());
+ OS::Print("LoadLocal(%s lvl:%d)",
+ comp->local().name().ToCString(), comp->context_level());
}
void FlowGraphPrinter::VisitStoreLocal(StoreLocalComp* comp) {
OS::Print("StoreLocal(%s, ", comp->local().name().ToCString());
comp->value()->Accept(this);
- OS::Print(")");
+ OS::Print(", lvl: %d)", comp->context_level());
}
@@ -1622,6 +1752,25 @@
}
+void FlowGraphPrinter::VisitAllocateContext(AllocateContextComp* comp) {
+ OS::Print("AllocateContext(%d)", comp->num_context_variables());
+}
+
+
+void FlowGraphPrinter::VisitChainContext(ChainContextComp* comp) {
+ OS::Print("ChainContext(");
+ comp->context_value()->Accept(this);
+ OS::Print(")");
+}
+
+
+void FlowGraphPrinter::VisitStoreContext(StoreContextComp* comp) {
+ OS::Print("StoreContext(");
+ comp->value()->Accept(this);
+ OS::Print(")");
+}
+
+
void FlowGraphPrinter::VisitJoinEntry(JoinEntryInstr* instr) {
OS::Print("%2d: [join]", reverse_index(instr->postorder_number()));
}
@@ -1807,7 +1956,8 @@
void FlowGraphBuilder::Bailout(const char* reason) {
const char* kFormat = "FlowGraphBuilder Bailout: %s %s";
- const char* function_name = parsed_function_.function().ToCString();
+ const char* function_name =
+ parsed_function_.function().ToCString();
regis 2012/03/23 20:50:25 New line not needed.
srdjan 2012/03/23 21:22:19 Done.
intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1;
char* chars = reinterpret_cast<char*>(
Isolate::Current()->current_zone()->Allocate(len));

Powered by Google App Engine
This is Rietveld 408576698