Chromium Code Reviews| Index: test/cctest/compiler/test-js-context-specialization.cc |
| diff --git a/test/cctest/compiler/test-js-context-specialization.cc b/test/cctest/compiler/test-js-context-specialization.cc |
| index 7b62f74587747ef5e0fa95c93e8160ccbc7626c5..c5db33ca5a20c03c777e8ddc12fa0ebf47e0b124 100644 |
| --- a/test/cctest/compiler/test-js-context-specialization.cc |
| +++ b/test/cctest/compiler/test-js-context-specialization.cc |
| @@ -55,46 +55,45 @@ TEST(ReduceJSLoadContext) { |
| // Make a context and initialize it a bit for this test. |
| Handle<Context> native = t.factory()->NewNativeContext(); |
| - Handle<Context> ctx1 = t.factory()->NewNativeContext(); |
| - Handle<Context> ctx2 = t.factory()->NewNativeContext(); |
| - ctx2->set_previous(*ctx1); |
| - ctx1->set_previous(*native); |
| + Handle<Context> subcontext1 = t.factory()->NewNativeContext(); |
| + Handle<Context> subcontext2 = t.factory()->NewNativeContext(); |
| + subcontext2->set_previous(*subcontext1); |
| + subcontext1->set_previous(*native); |
| Handle<Object> expected = t.factory()->InternalizeUtf8String("gboy!"); |
| const int slot = Context::GLOBAL_OBJECT_INDEX; |
| native->set(slot, *expected); |
| Node* const_context = t.jsgraph()->Constant(native); |
| + Node* deep_const_context = t.jsgraph()->Constant(subcontext2); |
| Node* param_context = t.NewNode(t.common()->Parameter(0), start); |
| JSContextSpecializer spec(t.info(), t.jsgraph(), const_context); |
| { |
| // Mutable slot, constant context, depth = 0 => do nothing. |
| - t.info()->SetContext(native); |
| Node* load = t.NewNode(t.javascript()->LoadContext(0, 0, false), |
| - const_context, start, start); |
| + const_context, const_context, start); |
| Reduction r = spec.ReduceJSLoadContext(load); |
| CHECK(!r.Changed()); |
| } |
| { |
| // Mutable slot, non-constant context, depth = 0 => do nothing. |
| - t.info()->SetContext(native); |
| Node* load = t.NewNode(t.javascript()->LoadContext(0, 0, false), |
| - param_context, start, start); |
| + param_context, param_context, start); |
| Reduction r = spec.ReduceJSLoadContext(load); |
| CHECK(!r.Changed()); |
| } |
| { |
| - // Mutable slot, non-constant context, depth > 0 => fold-in parent context. |
| - t.info()->SetContext(ctx2); |
| + // Mutable slot, constant context, depth > 0 => fold-in parent context. |
| Node* load = t.NewNode( |
| t.javascript()->LoadContext(2, Context::GLOBAL_EVAL_FUN_INDEX, false), |
| - param_context, start, start); |
| + deep_const_context, deep_const_context, start); |
| Reduction r = spec.ReduceJSLoadContext(load); |
| CHECK(r.Changed()); |
| - CHECK_EQ(IrOpcode::kHeapConstant, r.replacement()->InputAt(0)->opcode()); |
| - ValueMatcher<Handle<Context> > match(r.replacement()->InputAt(0)); |
| + Node* new_context_input = NodeProperties::GetValueInput(r.replacement(), 0); |
| + CHECK_EQ(IrOpcode::kHeapConstant, new_context_input->opcode()); |
| + ValueMatcher<Handle<Context> > match(new_context_input); |
| CHECK_EQ(*native, *match.Value()); |
| ContextAccess access = static_cast<Operator1<ContextAccess>*>( |
| r.replacement()->op())->parameter(); |
| @@ -105,9 +104,8 @@ TEST(ReduceJSLoadContext) { |
| { |
| // Immutable slot, constant context => specialize. |
| - t.info()->SetContext(native); |
| Node* load = t.NewNode(t.javascript()->LoadContext(0, slot, true), |
| - const_context, start, start); |
| + const_context, const_context, start); |
| Reduction r = spec.ReduceJSLoadContext(load); |
| CHECK(r.Changed()); |
| CHECK(r.replacement() != load); |
| @@ -117,22 +115,73 @@ TEST(ReduceJSLoadContext) { |
| CHECK_EQ(*expected, *match.Value()); |
| } |
| + // TODO(titzer): test with other kinds of contexts, e.g. a function context. |
| + // TODO(sigurds): test that loads below create context are not optimized |
| +} |
| + |
| + |
| +TEST(ReduceJSStoreContext) { |
| + ContextSpecializationTester t; |
| + |
| + Node* start = t.NewNode(t.common()->Start(0)); |
| + t.graph()->SetStart(start); |
| + |
| + // Make a context and initialize it a bit for this test. |
| + Handle<Context> native = t.factory()->NewNativeContext(); |
| + Handle<Context> subcontext1 = t.factory()->NewNativeContext(); |
| + Handle<Context> subcontext2 = t.factory()->NewNativeContext(); |
| + subcontext2->set_previous(*subcontext1); |
| + subcontext1->set_previous(*native); |
| + Handle<Object> expected = t.factory()->InternalizeUtf8String("gboy!"); |
| + const int slot = Context::GLOBAL_OBJECT_INDEX; |
| + native->set(slot, *expected); |
| + |
| + Node* const_context = t.jsgraph()->Constant(native); |
| + Node* deep_const_context = t.jsgraph()->Constant(subcontext2); |
| + Node* param_context = t.NewNode(t.common()->Parameter(0), start); |
| + JSContextSpecializer spec(t.info(), t.jsgraph(), const_context); |
| + |
| { |
| - // Immutable slot, non-constant context => specialize. |
| - t.info()->SetContext(native); |
| - Node* load = t.NewNode(t.javascript()->LoadContext(0, slot, true), |
| - param_context, start, start); |
| - Reduction r = spec.ReduceJSLoadContext(load); |
| - CHECK(r.Changed()); |
| - CHECK(r.replacement() != load); |
| + // Mutable slot, constant context, depth = 0 => do nothing. |
| + Node* load = t.NewNode(t.javascript()->StoreContext(0, 0), const_context, |
| + const_context, start); |
| + Reduction r = spec.ReduceJSStoreContext(load); |
| + CHECK(!r.Changed()); |
| + } |
| - ValueMatcher<Handle<Object> > match(r.replacement()); |
| - CHECK(match.HasValue()); |
| - CHECK_EQ(*expected, *match.Value()); |
| + { |
| + // Mutable slot, non-constant context, depth = 0 => do nothing. |
| + Node* load = t.NewNode(t.javascript()->StoreContext(0, 0), param_context, |
| + param_context, start); |
| + Reduction r = spec.ReduceJSStoreContext(load); |
| + CHECK(!r.Changed()); |
| } |
| - // TODO(titzer): test with other kinds of contexts, e.g. a function context. |
| - // TODO(sigurds): test that loads below create context are not optimized |
| + { |
| + // Immutable slot, constant context => do nothing. |
|
Michael Starzinger
2014/08/08 10:00:17
nit: maybe add "[...], depth = 0 [...]" here.
sigurds
2014/08/08 11:00:12
Done.
|
| + Node* load = t.NewNode(t.javascript()->StoreContext(0, slot), const_context, |
| + const_context, start); |
| + Reduction r = spec.ReduceJSStoreContext(load); |
| + CHECK(!r.Changed()); |
| + } |
| + |
| + { |
| + // Mutable slot, constant context, depth > 0 => fold-in parent context. |
| + Node* load = t.NewNode( |
| + t.javascript()->StoreContext(2, Context::GLOBAL_EVAL_FUN_INDEX), |
| + deep_const_context, deep_const_context, start); |
| + Reduction r = spec.ReduceJSStoreContext(load); |
| + CHECK(r.Changed()); |
| + Node* new_context_input = NodeProperties::GetValueInput(r.replacement(), 0); |
| + CHECK_EQ(IrOpcode::kHeapConstant, new_context_input->opcode()); |
| + ValueMatcher<Handle<Context> > match(new_context_input); |
| + CHECK_EQ(*native, *match.Value()); |
| + ContextAccess access = static_cast<Operator1<ContextAccess>*>( |
| + r.replacement()->op())->parameter(); |
| + CHECK_EQ(Context::GLOBAL_EVAL_FUN_INDEX, access.index()); |
| + CHECK_EQ(0, access.depth()); |
| + CHECK_EQ(false, access.immutable()); |
| + } |
| } |
| @@ -162,17 +211,25 @@ TEST(SpecializeToContext) { |
| { |
| // Check that SpecializeToContext() replaces values and forwards effects |
| // correctly, and folds values from constant and non-constant contexts |
| - Node* effect_in = t.NewNode(t.common()->Start(0)); |
| + Node* effect_in = start; |
| Node* load = t.NewNode(t.javascript()->LoadContext(0, slot, true), |
| - const_context, const_context, effect_in, start); |
| + const_context, const_context, effect_in); |
| Node* value_use = t.ChangeTaggedToInt32(load); |
| Node* other_load = t.NewNode(t.javascript()->LoadContext(0, slot, true), |
| - param_context, param_context, load, start); |
| + param_context, param_context, load); |
| Node* effect_use = other_load; |
| Node* other_use = t.ChangeTaggedToInt32(other_load); |
| + Node* add = t.NewNode(t.javascript()->Add(), value_use, other_use, |
| + param_context, other_load, start); |
| + |
| + Node* ret = t.NewNode(t.common()->Return(), add, effect_use, start); |
| + Node* end = t.NewNode(t.common()->End(), ret); |
| + USE(end); |
| + t.graph()->SetEnd(end); |
| + |
| // Double check the above graph is what we expect, or the test is broken. |
| CheckEffectInput(effect_in, load); |
| CheckEffectInput(load, effect_use); |