| OLD | NEW |
| 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-graph.h" | 6 #include "src/compiler/js-graph.h" |
| 7 #include "src/compiler/js-operator.h" | 7 #include "src/compiler/js-operator.h" |
| 8 #include "src/compiler/node-matchers.h" | 8 #include "src/compiler/node-matchers.h" |
| 9 #include "src/compiler/node-properties.h" | 9 #include "src/compiler/node-properties.h" |
| 10 #include "src/compiler/source-position.h" | 10 #include "src/compiler/source-position.h" |
| (...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 179 HeapObjectMatcher match(new_context_input); | 179 HeapObjectMatcher match(new_context_input); |
| 180 CHECK_EQ(*native, *match.Value()); | 180 CHECK_EQ(*native, *match.Value()); |
| 181 ContextAccess access = OpParameter<ContextAccess>(r.replacement()); | 181 ContextAccess access = OpParameter<ContextAccess>(r.replacement()); |
| 182 CHECK_EQ(Context::GLOBAL_EVAL_FUN_INDEX, static_cast<int>(access.index())); | 182 CHECK_EQ(Context::GLOBAL_EVAL_FUN_INDEX, static_cast<int>(access.index())); |
| 183 CHECK_EQ(0, static_cast<int>(access.depth())); | 183 CHECK_EQ(0, static_cast<int>(access.depth())); |
| 184 CHECK_EQ(false, access.immutable()); | 184 CHECK_EQ(false, access.immutable()); |
| 185 } | 185 } |
| 186 } | 186 } |
| 187 | 187 |
| 188 | 188 |
| 189 // TODO(titzer): factor out common code with effects checking in typed lowering. | |
| 190 static void CheckEffectInput(Node* effect, Node* use) { | |
| 191 CHECK_EQ(effect, NodeProperties::GetEffectInput(use)); | |
| 192 } | |
| 193 | |
| 194 | |
| 195 TEST(SpecializeToContext) { | |
| 196 ContextSpecializationTester t; | |
| 197 | |
| 198 Node* start = t.graph()->NewNode(t.common()->Start(0)); | |
| 199 t.graph()->SetStart(start); | |
| 200 | |
| 201 // Make a context and initialize it a bit for this test. | |
| 202 Handle<Context> native = t.factory()->NewNativeContext(); | |
| 203 Handle<Object> expected = t.factory()->InternalizeUtf8String("gboy!"); | |
| 204 const int slot = Context::NATIVE_CONTEXT_INDEX; | |
| 205 native->set(slot, *expected); | |
| 206 | |
| 207 Node* const_context = t.jsgraph()->Constant(native); | |
| 208 Node* param_context = t.graph()->NewNode(t.common()->Parameter(0), start); | |
| 209 | |
| 210 { | |
| 211 // Check that specialization replaces values and forwards effects | |
| 212 // correctly, and folds values from constant and non-constant contexts | |
| 213 Node* effect_in = start; | |
| 214 Node* load = t.graph()->NewNode(t.javascript()->LoadContext(0, slot, true), | |
| 215 const_context, const_context, effect_in); | |
| 216 | |
| 217 | |
| 218 Node* value_use = | |
| 219 t.graph()->NewNode(t.simplified()->ChangeTaggedToInt32(), load); | |
| 220 Node* other_load = | |
| 221 t.graph()->NewNode(t.javascript()->LoadContext(0, slot, true), | |
| 222 param_context, param_context, load); | |
| 223 Node* effect_use = other_load; | |
| 224 Node* other_use = | |
| 225 t.graph()->NewNode(t.simplified()->ChangeTaggedToInt32(), other_load); | |
| 226 | |
| 227 Node* add = t.graph()->NewNode( | |
| 228 t.javascript()->Add(BinaryOperationHints::Any()), value_use, other_use, | |
| 229 param_context, t.jsgraph()->EmptyFrameState(), | |
| 230 t.jsgraph()->EmptyFrameState(), other_load, start); | |
| 231 | |
| 232 Node* ret = | |
| 233 t.graph()->NewNode(t.common()->Return(), add, effect_use, start); | |
| 234 Node* end = t.graph()->NewNode(t.common()->End(1), ret); | |
| 235 USE(end); | |
| 236 t.graph()->SetEnd(end); | |
| 237 | |
| 238 // Double check the above graph is what we expect, or the test is broken. | |
| 239 CheckEffectInput(effect_in, load); | |
| 240 CheckEffectInput(load, effect_use); | |
| 241 | |
| 242 // Perform the reduction on the entire graph. | |
| 243 GraphReducer graph_reducer(t.main_zone(), t.graph()); | |
| 244 JSContextSpecialization spec(&graph_reducer, t.jsgraph(), | |
| 245 MaybeHandle<Context>()); | |
| 246 graph_reducer.AddReducer(&spec); | |
| 247 graph_reducer.ReduceGraph(); | |
| 248 | |
| 249 // Effects should have been forwarded (not replaced with a value). | |
| 250 CheckEffectInput(effect_in, effect_use); | |
| 251 | |
| 252 // Use of {other_load} should not have been replaced. | |
| 253 CHECK_EQ(other_load, other_use->InputAt(0)); | |
| 254 | |
| 255 Node* replacement = value_use->InputAt(0); | |
| 256 HeapObjectMatcher match(replacement); | |
| 257 CHECK(match.HasValue()); | |
| 258 CHECK_EQ(*expected, *match.Value()); | |
| 259 } | |
| 260 // TODO(titzer): clean up above test and test more complicated effects. | |
| 261 } | |
| 262 | |
| 263 | |
| 264 TEST(SpecializeJSFunction_ToConstant1) { | 189 TEST(SpecializeJSFunction_ToConstant1) { |
| 265 FunctionTester T( | 190 FunctionTester T( |
| 266 "(function() { var x = 1; function inc(a)" | 191 "(function() { var x = 1; function inc(a)" |
| 267 " { return a + x; } return inc; })()"); | 192 " { return a + x; } return inc; })()"); |
| 268 | 193 |
| 269 T.CheckCall(1.0, 0.0, 0.0); | 194 T.CheckCall(1.0, 0.0, 0.0); |
| 270 T.CheckCall(2.0, 1.0, 0.0); | 195 T.CheckCall(2.0, 1.0, 0.0); |
| 271 T.CheckCall(2.1, 1.1, 0.0); | 196 T.CheckCall(2.1, 1.1, 0.0); |
| 272 } | 197 } |
| 273 | 198 |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 313 | 238 |
| 314 CHECK(T.Call(T.Val(0.0), T.Val(0.0)).ToHandleChecked()->IsNaN()); | 239 CHECK(T.Call(T.Val(0.0), T.Val(0.0)).ToHandleChecked()->IsNaN()); |
| 315 CHECK(T.Call(T.Val(2.0), T.Val(0.0)).ToHandleChecked()->IsNaN()); | 240 CHECK(T.Call(T.Val(2.0), T.Val(0.0)).ToHandleChecked()->IsNaN()); |
| 316 CHECK(T.Call(T.Val(-2.1), T.Val(0.0)).ToHandleChecked()->IsNaN()); | 241 CHECK(T.Call(T.Val(-2.1), T.Val(0.0)).ToHandleChecked()->IsNaN()); |
| 317 } | 242 } |
| 318 } | 243 } |
| 319 | 244 |
| 320 } // namespace compiler | 245 } // namespace compiler |
| 321 } // namespace internal | 246 } // namespace internal |
| 322 } // namespace v8 | 247 } // namespace v8 |
| OLD | NEW |