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

Side by Side Diff: src/compiler/js-context-specialization.cc

Issue 440053002: Update and extend context specialization. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Update and extend context specialization. Created 6 years, 4 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2014 the V8 project authors. All rights reserved. 1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/compiler/common-operator.h" 5 #include "src/compiler/common-operator.h"
6 #include "src/compiler/generic-node-inl.h" 6 #include "src/compiler/generic-node-inl.h"
7 #include "src/compiler/graph-inl.h"
7 #include "src/compiler/js-context-specialization.h" 8 #include "src/compiler/js-context-specialization.h"
8 #include "src/compiler/js-operator.h" 9 #include "src/compiler/js-operator.h"
9 #include "src/compiler/node-aux-data-inl.h" 10 #include "src/compiler/node-aux-data-inl.h"
10 #include "src/compiler/node-matchers.h" 11 #include "src/compiler/node-matchers.h"
11 #include "src/compiler/node-properties-inl.h" 12 #include "src/compiler/node-properties-inl.h"
12 13
13 namespace v8 { 14 namespace v8 {
14 namespace internal { 15 namespace internal {
15 namespace compiler { 16 namespace compiler {
16 17
17 // TODO(titzer): factor this out to a common routine with js-typed-lowering. 18 // TODO(titzer): factor this out to a common routine with js-typed-lowering.
18 static void ReplaceEffectfulWithValue(Node* node, Node* value) { 19 static void ReplaceEffectfulWithValue(Node* node, Node* value) {
19 Node* effect = NodeProperties::GetEffectInput(node); 20 Node* effect = NULL;
21 if (OperatorProperties::HasEffectInput(node->op())) {
22 effect = NodeProperties::GetEffectInput(node);
23 }
20 24
21 // Requires distinguishing between value and effect edges. 25 // Requires distinguishing between value and effect edges.
22 UseIter iter = node->uses().begin(); 26 UseIter iter = node->uses().begin();
23 while (iter != node->uses().end()) { 27 while (iter != node->uses().end()) {
24 if (NodeProperties::IsEffectEdge(iter.edge())) { 28 if (NodeProperties::IsEffectEdge(iter.edge())) {
29 DCHECK_NE(NULL, effect);
25 iter = iter.UpdateToAndIncrement(effect); 30 iter = iter.UpdateToAndIncrement(effect);
26 } else { 31 } else {
27 iter = iter.UpdateToAndIncrement(value); 32 iter = iter.UpdateToAndIncrement(value);
28 } 33 }
29 } 34 }
30 } 35 }
31 36
32 37
38 class ContextSpecializationVisitor : public NullNodeVisitor {
39 public:
40 explicit ContextSpecializationVisitor(JSContextSpecializer* spec)
41 : spec_(spec) {}
42
43 GenericGraphVisit::Control Post(Node* node) {
44 switch (node->opcode()) {
45 case IrOpcode::kJSLoadContext: {
46 Reduction r = spec_->ReduceJSLoadContext(node);
47 if (r.Changed() && r.replacement() != node) {
48 ReplaceEffectfulWithValue(node, r.replacement());
49 }
50 break;
51 }
52 case IrOpcode::kJSStoreContext: {
53 Reduction r = spec_->ReduceJSStoreContext(node);
54 if (r.Changed() && r.replacement() != node) {
55 ReplaceEffectfulWithValue(node, r.replacement());
56 }
57 break;
58 }
59 default:
60 break;
61 }
62 return GenericGraphVisit::CONTINUE;
63 }
64
65 private:
66 JSContextSpecializer* spec_;
67 };
68
69
33 void JSContextSpecializer::SpecializeToContext() { 70 void JSContextSpecializer::SpecializeToContext() {
34 ValueMatcher<Handle<Context> > match(context_); 71 ReplaceEffectfulWithValue(context_, jsgraph_->Constant(info_->context()));
35 72
36 // Iterate over all uses of the context and try to replace {LoadContext} 73 ContextSpecializationVisitor visitor(this);
37 // nodes with their values from the constant context. 74 jsgraph_->graph()->VisitNodeInputsFromEnd(&visitor);
38 UseIter iter = match.node()->uses().begin();
39 while (iter != match.node()->uses().end()) {
40 Node* use = *iter;
41 if (use->opcode() == IrOpcode::kJSLoadContext) {
42 Reduction r = ReduceJSLoadContext(use);
43 if (r.Changed() && r.replacement() != use) {
44 ReplaceEffectfulWithValue(use, r.replacement());
45 }
46 }
47 ++iter;
48 }
49 } 75 }
50 76
51 77
52 Reduction JSContextSpecializer::ReduceJSLoadContext(Node* node) { 78 Reduction JSContextSpecializer::ReduceJSLoadContext(Node* node) {
53 DCHECK_EQ(IrOpcode::kJSLoadContext, node->opcode()); 79 DCHECK_EQ(IrOpcode::kJSLoadContext, node->opcode());
54 80
55 ContextAccess access = 81 ValueMatcher<Handle<Context> > match(NodeProperties::GetValueInput(node, 0));
56 static_cast<Operator1<ContextAccess>*>(node->op())->parameter(); 82 // If the context is not constant, no reduction can occur.
83 if (!match.HasValue()) {
84 return Reducer::NoChange();
85 }
86
87 ContextAccess access = OpParameter<ContextAccess>(node);
57 88
58 // Find the right parent context. 89 // Find the right parent context.
59 Context* context = *info_->context(); 90 Context* context = *match.Value();
60 for (int i = access.depth(); i > 0; --i) { 91 for (int i = access.depth(); i > 0; --i) {
61 context = context->previous(); 92 context = context->previous();
62 } 93 }
63 94
64 // If the access itself is mutable, only fold-in the parent. 95 // If the access itself is mutable, only fold-in the parent.
65 if (!access.immutable()) { 96 if (!access.immutable()) {
66 // The access does not have to look up a parent, nothing to fold. 97 // The access does not have to look up a parent, nothing to fold.
67 if (access.depth() == 0) { 98 if (access.depth() == 0) {
68 return Reducer::NoChange(); 99 return Reducer::NoChange();
69 } 100 }
70 Operator* op = jsgraph_->javascript()->LoadContext(0, access.index(), 101 Operator* op = jsgraph_->javascript()->LoadContext(0, access.index(),
71 access.immutable()); 102 access.immutable());
72 node->set_op(op); 103 node->set_op(op);
73 Handle<Object> context_handle = Handle<Object>(context, info_->isolate()); 104 Handle<Object> context_handle = Handle<Object>(context, info_->isolate());
74 node->ReplaceInput(0, jsgraph_->Constant(context_handle)); 105 node->ReplaceInput(0, jsgraph_->Constant(context_handle));
75 return Reducer::Changed(node); 106 return Reducer::Changed(node);
76 } 107 }
77 Handle<Object> value = 108 Handle<Object> value =
78 Handle<Object>(context->get(access.index()), info_->isolate()); 109 Handle<Object>(context->get(access.index()), info_->isolate());
79 110
80 // Even though the context slot is immutable, the context might have escaped 111 // Even though the context slot is immutable, the context might have escaped
81 // before the function to which it belongs has initialized the slot. 112 // before the function to which it belongs has initialized the slot.
82 // We must be conservative and check if the value in the slot is currently the 113 // We must be conservative and check if the value in the slot is currently the
83 // hole or undefined. If it is neither of these, then it must be initialized. 114 // hole or undefined. If it is neither of these, then it must be initialized.
84 if (value->IsUndefined() || value->IsTheHole()) return Reducer::NoChange(); 115 if (value->IsUndefined() || value->IsTheHole()) {
116 return Reducer::NoChange();
117 }
85 118
86 // Success. The context load can be replaced with the constant. 119 // Success. The context load can be replaced with the constant.
87 // TODO(titzer): record the specialization for sharing code across multiple 120 // TODO(titzer): record the specialization for sharing code across multiple
88 // contexts that have the same value in the corresponding context slot. 121 // contexts that have the same value in the corresponding context slot.
89 return Reducer::Replace(jsgraph_->Constant(value)); 122 return Reducer::Replace(jsgraph_->Constant(value));
90 } 123 }
124
125
126 Reduction JSContextSpecializer::ReduceJSStoreContext(Node* node) {
127 DCHECK_EQ(IrOpcode::kJSStoreContext, node->opcode());
128
129 ValueMatcher<Handle<Context> > match(NodeProperties::GetValueInput(node, 0));
130 // If the context is not constant, no reduction can occur.
131 if (!match.HasValue()) {
132 return Reducer::NoChange();
133 }
134
135 ContextAccess access =
136 static_cast<Operator1<ContextAccess>*>(node->op())->parameter();
137
138 // The access does not have to look up a parent, nothing to fold.
139 if (access.depth() == 0) {
140 return Reducer::NoChange();
141 }
142
143 // Find the right parent context.
144 Context* context = *match.Value();
145 for (int i = access.depth(); i > 0; --i) {
146 context = context->previous();
147 }
148
149 Operator* op = jsgraph_->javascript()->StoreContext(0, access.index());
150 node->set_op(op);
151 Handle<Object> new_context_handle = Handle<Object>(context, info_->isolate());
152 node->ReplaceInput(0, jsgraph_->Constant(new_context_handle));
153
154 return Reducer::Changed(node);
155 }
91 } 156 }
92 } 157 }
93 } // namespace v8::internal::compiler 158 } // namespace v8::internal::compiler
OLDNEW
« no previous file with comments | « src/compiler/js-context-specialization.h ('k') | test/cctest/compiler/test-js-context-specialization.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698