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

Side by Side Diff: test/cctest/compiler/test-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
« no previous file with comments | « src/compiler/js-context-specialization.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/js-context-specialization.h" 5 #include "src/compiler/js-context-specialization.h"
6 #include "src/compiler/js-operator.h" 6 #include "src/compiler/js-operator.h"
7 #include "src/compiler/node-matchers.h" 7 #include "src/compiler/node-matchers.h"
8 #include "src/compiler/node-properties-inl.h" 8 #include "src/compiler/node-properties-inl.h"
9 #include "src/compiler/simplified-node-factory.h" 9 #include "src/compiler/simplified-node-factory.h"
10 #include "src/compiler/source-position.h" 10 #include "src/compiler/source-position.h"
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
48 48
49 49
50 TEST(ReduceJSLoadContext) { 50 TEST(ReduceJSLoadContext) {
51 ContextSpecializationTester t; 51 ContextSpecializationTester t;
52 52
53 Node* start = t.NewNode(t.common()->Start(0)); 53 Node* start = t.NewNode(t.common()->Start(0));
54 t.graph()->SetStart(start); 54 t.graph()->SetStart(start);
55 55
56 // Make a context and initialize it a bit for this test. 56 // Make a context and initialize it a bit for this test.
57 Handle<Context> native = t.factory()->NewNativeContext(); 57 Handle<Context> native = t.factory()->NewNativeContext();
58 Handle<Context> ctx1 = t.factory()->NewNativeContext(); 58 Handle<Context> subcontext1 = t.factory()->NewNativeContext();
59 Handle<Context> ctx2 = t.factory()->NewNativeContext(); 59 Handle<Context> subcontext2 = t.factory()->NewNativeContext();
60 ctx2->set_previous(*ctx1); 60 subcontext2->set_previous(*subcontext1);
61 ctx1->set_previous(*native); 61 subcontext1->set_previous(*native);
62 Handle<Object> expected = t.factory()->InternalizeUtf8String("gboy!"); 62 Handle<Object> expected = t.factory()->InternalizeUtf8String("gboy!");
63 const int slot = Context::GLOBAL_OBJECT_INDEX; 63 const int slot = Context::GLOBAL_OBJECT_INDEX;
64 native->set(slot, *expected); 64 native->set(slot, *expected);
65 65
66 Node* const_context = t.jsgraph()->Constant(native); 66 Node* const_context = t.jsgraph()->Constant(native);
67 Node* deep_const_context = t.jsgraph()->Constant(subcontext2);
67 Node* param_context = t.NewNode(t.common()->Parameter(0), start); 68 Node* param_context = t.NewNode(t.common()->Parameter(0), start);
68 JSContextSpecializer spec(t.info(), t.jsgraph(), const_context); 69 JSContextSpecializer spec(t.info(), t.jsgraph(), const_context);
69 70
70 { 71 {
71 // Mutable slot, constant context, depth = 0 => do nothing. 72 // Mutable slot, constant context, depth = 0 => do nothing.
72 t.info()->SetContext(native);
73 Node* load = t.NewNode(t.javascript()->LoadContext(0, 0, false), 73 Node* load = t.NewNode(t.javascript()->LoadContext(0, 0, false),
74 const_context, start, start); 74 const_context, const_context, start);
75 Reduction r = spec.ReduceJSLoadContext(load); 75 Reduction r = spec.ReduceJSLoadContext(load);
76 CHECK(!r.Changed()); 76 CHECK(!r.Changed());
77 } 77 }
78 78
79 { 79 {
80 // Mutable slot, non-constant context, depth = 0 => do nothing. 80 // Mutable slot, non-constant context, depth = 0 => do nothing.
81 t.info()->SetContext(native);
82 Node* load = t.NewNode(t.javascript()->LoadContext(0, 0, false), 81 Node* load = t.NewNode(t.javascript()->LoadContext(0, 0, false),
83 param_context, start, start); 82 param_context, param_context, start);
84 Reduction r = spec.ReduceJSLoadContext(load); 83 Reduction r = spec.ReduceJSLoadContext(load);
85 CHECK(!r.Changed()); 84 CHECK(!r.Changed());
86 } 85 }
87 86
88 { 87 {
89 // Mutable slot, non-constant context, depth > 0 => fold-in parent context. 88 // Mutable slot, constant context, depth > 0 => fold-in parent context.
90 t.info()->SetContext(ctx2);
91 Node* load = t.NewNode( 89 Node* load = t.NewNode(
92 t.javascript()->LoadContext(2, Context::GLOBAL_EVAL_FUN_INDEX, false), 90 t.javascript()->LoadContext(2, Context::GLOBAL_EVAL_FUN_INDEX, false),
93 param_context, start, start); 91 deep_const_context, deep_const_context, start);
94 Reduction r = spec.ReduceJSLoadContext(load); 92 Reduction r = spec.ReduceJSLoadContext(load);
95 CHECK(r.Changed()); 93 CHECK(r.Changed());
96 CHECK_EQ(IrOpcode::kHeapConstant, r.replacement()->InputAt(0)->opcode()); 94 Node* new_context_input = NodeProperties::GetValueInput(r.replacement(), 0);
97 ValueMatcher<Handle<Context> > match(r.replacement()->InputAt(0)); 95 CHECK_EQ(IrOpcode::kHeapConstant, new_context_input->opcode());
96 ValueMatcher<Handle<Context> > match(new_context_input);
98 CHECK_EQ(*native, *match.Value()); 97 CHECK_EQ(*native, *match.Value());
99 ContextAccess access = static_cast<Operator1<ContextAccess>*>( 98 ContextAccess access = static_cast<Operator1<ContextAccess>*>(
100 r.replacement()->op())->parameter(); 99 r.replacement()->op())->parameter();
101 CHECK_EQ(Context::GLOBAL_EVAL_FUN_INDEX, access.index()); 100 CHECK_EQ(Context::GLOBAL_EVAL_FUN_INDEX, access.index());
102 CHECK_EQ(0, access.depth()); 101 CHECK_EQ(0, access.depth());
103 CHECK_EQ(false, access.immutable()); 102 CHECK_EQ(false, access.immutable());
104 } 103 }
105 104
106 { 105 {
107 // Immutable slot, constant context => specialize. 106 // Immutable slot, constant context, depth = 0 => specialize.
108 t.info()->SetContext(native);
109 Node* load = t.NewNode(t.javascript()->LoadContext(0, slot, true), 107 Node* load = t.NewNode(t.javascript()->LoadContext(0, slot, true),
110 const_context, start, start); 108 const_context, const_context, start);
111 Reduction r = spec.ReduceJSLoadContext(load); 109 Reduction r = spec.ReduceJSLoadContext(load);
112 CHECK(r.Changed()); 110 CHECK(r.Changed());
113 CHECK(r.replacement() != load); 111 CHECK(r.replacement() != load);
114 112
115 ValueMatcher<Handle<Object> > match(r.replacement()); 113 ValueMatcher<Handle<Object> > match(r.replacement());
116 CHECK(match.HasValue()); 114 CHECK(match.HasValue());
117 CHECK_EQ(*expected, *match.Value()); 115 CHECK_EQ(*expected, *match.Value());
118 } 116 }
119 117
120 {
121 // Immutable slot, non-constant context => specialize.
122 t.info()->SetContext(native);
123 Node* load = t.NewNode(t.javascript()->LoadContext(0, slot, true),
124 param_context, start, start);
125 Reduction r = spec.ReduceJSLoadContext(load);
126 CHECK(r.Changed());
127 CHECK(r.replacement() != load);
128
129 ValueMatcher<Handle<Object> > match(r.replacement());
130 CHECK(match.HasValue());
131 CHECK_EQ(*expected, *match.Value());
132 }
133
134 // TODO(titzer): test with other kinds of contexts, e.g. a function context. 118 // TODO(titzer): test with other kinds of contexts, e.g. a function context.
135 // TODO(sigurds): test that loads below create context are not optimized 119 // TODO(sigurds): test that loads below create context are not optimized
136 } 120 }
137 121
138 122
123 TEST(ReduceJSStoreContext) {
124 ContextSpecializationTester t;
125
126 Node* start = t.NewNode(t.common()->Start(0));
127 t.graph()->SetStart(start);
128
129 // Make a context and initialize it a bit for this test.
130 Handle<Context> native = t.factory()->NewNativeContext();
131 Handle<Context> subcontext1 = t.factory()->NewNativeContext();
132 Handle<Context> subcontext2 = t.factory()->NewNativeContext();
133 subcontext2->set_previous(*subcontext1);
134 subcontext1->set_previous(*native);
135 Handle<Object> expected = t.factory()->InternalizeUtf8String("gboy!");
136 const int slot = Context::GLOBAL_OBJECT_INDEX;
137 native->set(slot, *expected);
138
139 Node* const_context = t.jsgraph()->Constant(native);
140 Node* deep_const_context = t.jsgraph()->Constant(subcontext2);
141 Node* param_context = t.NewNode(t.common()->Parameter(0), start);
142 JSContextSpecializer spec(t.info(), t.jsgraph(), const_context);
143
144 {
145 // Mutable slot, constant context, depth = 0 => do nothing.
146 Node* load = t.NewNode(t.javascript()->StoreContext(0, 0), const_context,
147 const_context, start);
148 Reduction r = spec.ReduceJSStoreContext(load);
149 CHECK(!r.Changed());
150 }
151
152 {
153 // Mutable slot, non-constant context, depth = 0 => do nothing.
154 Node* load = t.NewNode(t.javascript()->StoreContext(0, 0), param_context,
155 param_context, start);
156 Reduction r = spec.ReduceJSStoreContext(load);
157 CHECK(!r.Changed());
158 }
159
160 {
161 // Immutable slot, constant context, depth = 0 => do nothing.
162 Node* load = t.NewNode(t.javascript()->StoreContext(0, slot), const_context,
163 const_context, start);
164 Reduction r = spec.ReduceJSStoreContext(load);
165 CHECK(!r.Changed());
166 }
167
168 {
169 // Mutable slot, constant context, depth > 0 => fold-in parent context.
170 Node* load = t.NewNode(
171 t.javascript()->StoreContext(2, Context::GLOBAL_EVAL_FUN_INDEX),
172 deep_const_context, deep_const_context, start);
173 Reduction r = spec.ReduceJSStoreContext(load);
174 CHECK(r.Changed());
175 Node* new_context_input = NodeProperties::GetValueInput(r.replacement(), 0);
176 CHECK_EQ(IrOpcode::kHeapConstant, new_context_input->opcode());
177 ValueMatcher<Handle<Context> > match(new_context_input);
178 CHECK_EQ(*native, *match.Value());
179 ContextAccess access = static_cast<Operator1<ContextAccess>*>(
180 r.replacement()->op())->parameter();
181 CHECK_EQ(Context::GLOBAL_EVAL_FUN_INDEX, access.index());
182 CHECK_EQ(0, access.depth());
183 CHECK_EQ(false, access.immutable());
184 }
185 }
186
187
139 // TODO(titzer): factor out common code with effects checking in typed lowering. 188 // TODO(titzer): factor out common code with effects checking in typed lowering.
140 static void CheckEffectInput(Node* effect, Node* use) { 189 static void CheckEffectInput(Node* effect, Node* use) {
141 CHECK_EQ(effect, NodeProperties::GetEffectInput(use)); 190 CHECK_EQ(effect, NodeProperties::GetEffectInput(use));
142 } 191 }
143 192
144 193
145 TEST(SpecializeToContext) { 194 TEST(SpecializeToContext) {
146 ContextSpecializationTester t; 195 ContextSpecializationTester t;
147 196
148 Node* start = t.NewNode(t.common()->Start(0)); 197 Node* start = t.NewNode(t.common()->Start(0));
149 t.graph()->SetStart(start); 198 t.graph()->SetStart(start);
150 199
151 // Make a context and initialize it a bit for this test. 200 // Make a context and initialize it a bit for this test.
152 Handle<Context> native = t.factory()->NewNativeContext(); 201 Handle<Context> native = t.factory()->NewNativeContext();
153 Handle<Object> expected = t.factory()->InternalizeUtf8String("gboy!"); 202 Handle<Object> expected = t.factory()->InternalizeUtf8String("gboy!");
154 const int slot = Context::GLOBAL_OBJECT_INDEX; 203 const int slot = Context::GLOBAL_OBJECT_INDEX;
155 native->set(slot, *expected); 204 native->set(slot, *expected);
156 t.info()->SetContext(native); 205 t.info()->SetContext(native);
157 206
158 Node* const_context = t.jsgraph()->Constant(native); 207 Node* const_context = t.jsgraph()->Constant(native);
159 Node* param_context = t.NewNode(t.common()->Parameter(0), start); 208 Node* param_context = t.NewNode(t.common()->Parameter(0), start);
160 JSContextSpecializer spec(t.info(), t.jsgraph(), const_context); 209 JSContextSpecializer spec(t.info(), t.jsgraph(), const_context);
161 210
162 { 211 {
163 // Check that SpecializeToContext() replaces values and forwards effects 212 // Check that SpecializeToContext() replaces values and forwards effects
164 // correctly, and folds values from constant and non-constant contexts 213 // correctly, and folds values from constant and non-constant contexts
165 Node* effect_in = t.NewNode(t.common()->Start(0)); 214 Node* effect_in = start;
166 Node* load = t.NewNode(t.javascript()->LoadContext(0, slot, true), 215 Node* load = t.NewNode(t.javascript()->LoadContext(0, slot, true),
167 const_context, const_context, effect_in, start); 216 const_context, const_context, effect_in);
168 217
169 218
170 Node* value_use = t.ChangeTaggedToInt32(load); 219 Node* value_use = t.ChangeTaggedToInt32(load);
171 Node* other_load = t.NewNode(t.javascript()->LoadContext(0, slot, true), 220 Node* other_load = t.NewNode(t.javascript()->LoadContext(0, slot, true),
172 param_context, param_context, load, start); 221 param_context, param_context, load);
173 Node* effect_use = other_load; 222 Node* effect_use = other_load;
174 Node* other_use = t.ChangeTaggedToInt32(other_load); 223 Node* other_use = t.ChangeTaggedToInt32(other_load);
175 224
225 Node* add = t.NewNode(t.javascript()->Add(), value_use, other_use,
226 param_context, other_load, start);
227
228 Node* ret = t.NewNode(t.common()->Return(), add, effect_use, start);
229 Node* end = t.NewNode(t.common()->End(), ret);
230 USE(end);
231 t.graph()->SetEnd(end);
232
176 // Double check the above graph is what we expect, or the test is broken. 233 // Double check the above graph is what we expect, or the test is broken.
177 CheckEffectInput(effect_in, load); 234 CheckEffectInput(effect_in, load);
178 CheckEffectInput(load, effect_use); 235 CheckEffectInput(load, effect_use);
179 236
180 // Perform the substitution on the entire graph. 237 // Perform the substitution on the entire graph.
181 spec.SpecializeToContext(); 238 spec.SpecializeToContext();
182 239
183 // Effects should have been forwarded (not replaced with a value). 240 // Effects should have been forwarded (not replaced with a value).
184 CheckEffectInput(effect_in, effect_use); 241 CheckEffectInput(effect_in, effect_use);
185 242
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
243 { 300 {
244 FunctionTester T( 301 FunctionTester T(
245 "(function() { if (false) { var x = 1; } function inc(a)" 302 "(function() { if (false) { var x = 1; } function inc(a)"
246 " { return a + x; } return inc; })()"); // x is undefined! 303 " { return a + x; } return inc; })()"); // x is undefined!
247 304
248 CHECK(T.Call(T.Val(0.0), T.Val(0.0)).ToHandleChecked()->IsNaN()); 305 CHECK(T.Call(T.Val(0.0), T.Val(0.0)).ToHandleChecked()->IsNaN());
249 CHECK(T.Call(T.Val(2.0), T.Val(0.0)).ToHandleChecked()->IsNaN()); 306 CHECK(T.Call(T.Val(2.0), T.Val(0.0)).ToHandleChecked()->IsNaN());
250 CHECK(T.Call(T.Val(-2.1), T.Val(0.0)).ToHandleChecked()->IsNaN()); 307 CHECK(T.Call(T.Val(-2.1), T.Val(0.0)).ToHandleChecked()->IsNaN());
251 } 308 }
252 } 309 }
OLDNEW
« no previous file with comments | « src/compiler/js-context-specialization.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698