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

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
« no previous file with comments | « runtime/vm/flow_graph_builder.h ('k') | runtime/vm/flow_graph_compiler_x64.cc » ('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 5792)
+++ 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()));
}
@@ -800,9 +819,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 +1174,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 +1204,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 +1303,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 +1331,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 +1414,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 +1602,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 +1751,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()));
}
« no previous file with comments | « runtime/vm/flow_graph_builder.h ('k') | runtime/vm/flow_graph_compiler_x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698