| 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-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/source-position.h" | 9 #include "src/compiler/source-position.h" | 
| 10 #include "src/compiler/typer.h" | 10 #include "src/compiler/typer.h" | 
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 62   const int slot = Context::GLOBAL_OBJECT_INDEX; | 62   const int slot = Context::GLOBAL_OBJECT_INDEX; | 
| 63   native->set(slot, *expected); | 63   native->set(slot, *expected); | 
| 64 | 64 | 
| 65   Node* const_context = t.jsgraph()->Constant(native); | 65   Node* const_context = t.jsgraph()->Constant(native); | 
| 66   Node* deep_const_context = t.jsgraph()->Constant(subcontext2); | 66   Node* deep_const_context = t.jsgraph()->Constant(subcontext2); | 
| 67   Node* param_context = t.NewNode(t.common()->Parameter(0), start); | 67   Node* param_context = t.NewNode(t.common()->Parameter(0), start); | 
| 68   JSContextSpecializer spec(t.info(), t.jsgraph(), const_context); | 68   JSContextSpecializer spec(t.info(), t.jsgraph(), const_context); | 
| 69 | 69 | 
| 70   { | 70   { | 
| 71     // Mutable slot, constant context, depth = 0 => do nothing. | 71     // Mutable slot, constant context, depth = 0 => do nothing. | 
| 72     Node* load = t.NewNode(t.javascript()->LoadContext(0, 0, false), | 72     Node* load = t.NewNode(t.javascript()->LoadContext(ContextAccess(0, 0)), | 
| 73                            const_context, const_context, start); | 73                            const_context, const_context, start); | 
| 74     Reduction r = spec.ReduceJSLoadContext(load); | 74     Reduction r = spec.ReduceJSLoadContext(load); | 
| 75     CHECK(!r.Changed()); | 75     CHECK(!r.Changed()); | 
| 76   } | 76   } | 
| 77 | 77 | 
| 78   { | 78   { | 
| 79     // Mutable slot, non-constant context, depth = 0 => do nothing. | 79     // Mutable slot, non-constant context, depth = 0 => do nothing. | 
| 80     Node* load = t.NewNode(t.javascript()->LoadContext(0, 0, false), | 80     Node* load = t.NewNode(t.javascript()->LoadContext(ContextAccess(0, 0)), | 
| 81                            param_context, param_context, start); | 81                            param_context, param_context, start); | 
| 82     Reduction r = spec.ReduceJSLoadContext(load); | 82     Reduction r = spec.ReduceJSLoadContext(load); | 
| 83     CHECK(!r.Changed()); | 83     CHECK(!r.Changed()); | 
| 84   } | 84   } | 
| 85 | 85 | 
| 86   { | 86   { | 
| 87     // Mutable slot, constant context, depth > 0 => fold-in parent context. | 87     // Mutable slot, constant context, depth > 0 => fold-in parent context. | 
| 88     Node* load = t.NewNode( | 88     Node* load = t.NewNode(t.javascript()->LoadContext(ContextAccess( | 
| 89         t.javascript()->LoadContext(2, Context::GLOBAL_EVAL_FUN_INDEX, false), | 89                                2, Context::GLOBAL_EVAL_FUN_INDEX)), | 
| 90         deep_const_context, deep_const_context, start); | 90                            deep_const_context, deep_const_context, start); | 
| 91     Reduction r = spec.ReduceJSLoadContext(load); | 91     Reduction r = spec.ReduceJSLoadContext(load); | 
| 92     CHECK(r.Changed()); | 92     CHECK(r.Changed()); | 
| 93     Node* new_context_input = NodeProperties::GetValueInput(r.replacement(), 0); | 93     Node* new_context_input = NodeProperties::GetValueInput(r.replacement(), 0); | 
| 94     CHECK_EQ(IrOpcode::kHeapConstant, new_context_input->opcode()); | 94     CHECK_EQ(IrOpcode::kHeapConstant, new_context_input->opcode()); | 
| 95     HeapObjectMatcher<Context> match(new_context_input); | 95     HeapObjectMatcher<Context> match(new_context_input); | 
| 96     CHECK_EQ(*native, *match.Value().handle()); | 96     CHECK_EQ(*native, *match.Value().handle()); | 
| 97     ContextAccess access = OpParameter<ContextAccess>(r.replacement()); | 97     ContextAccess access = OpParameter<ContextAccess>(r.replacement()); | 
| 98     CHECK_EQ(Context::GLOBAL_EVAL_FUN_INDEX, access.index()); | 98     CHECK_EQ(Context::GLOBAL_EVAL_FUN_INDEX, access.index()); | 
| 99     CHECK_EQ(0, access.depth()); | 99     CHECK_EQ(0, access.depth()); | 
| 100     CHECK_EQ(false, access.immutable()); | 100     CHECK_EQ(false, access.immutable()); | 
| 101   } | 101   } | 
| 102 | 102 | 
| 103   { | 103   { | 
| 104     // Immutable slot, constant context, depth = 0 => specialize. | 104     // Immutable slot, constant context, depth = 0 => specialize. | 
| 105     Node* load = t.NewNode(t.javascript()->LoadContext(0, slot, true), | 105     Node* load = | 
| 106                            const_context, const_context, start); | 106         t.NewNode(t.javascript()->LoadContext(ContextAccess(0, slot, true)), | 
|  | 107                   const_context, const_context, start); | 
| 107     Reduction r = spec.ReduceJSLoadContext(load); | 108     Reduction r = spec.ReduceJSLoadContext(load); | 
| 108     CHECK(r.Changed()); | 109     CHECK(r.Changed()); | 
| 109     CHECK(r.replacement() != load); | 110     CHECK(r.replacement() != load); | 
| 110 | 111 | 
| 111     HeapObjectMatcher<Object> match(r.replacement()); | 112     HeapObjectMatcher<Object> match(r.replacement()); | 
| 112     CHECK(match.HasValue()); | 113     CHECK(match.HasValue()); | 
| 113     CHECK_EQ(*expected, *match.Value().handle()); | 114     CHECK_EQ(*expected, *match.Value().handle()); | 
| 114   } | 115   } | 
| 115 | 116 | 
| 116   // TODO(titzer): test with other kinds of contexts, e.g. a function context. | 117   // TODO(titzer): test with other kinds of contexts, e.g. a function context. | 
| (...skipping 17 matching lines...) Expand all  Loading... | 
| 134   const int slot = Context::GLOBAL_OBJECT_INDEX; | 135   const int slot = Context::GLOBAL_OBJECT_INDEX; | 
| 135   native->set(slot, *expected); | 136   native->set(slot, *expected); | 
| 136 | 137 | 
| 137   Node* const_context = t.jsgraph()->Constant(native); | 138   Node* const_context = t.jsgraph()->Constant(native); | 
| 138   Node* deep_const_context = t.jsgraph()->Constant(subcontext2); | 139   Node* deep_const_context = t.jsgraph()->Constant(subcontext2); | 
| 139   Node* param_context = t.NewNode(t.common()->Parameter(0), start); | 140   Node* param_context = t.NewNode(t.common()->Parameter(0), start); | 
| 140   JSContextSpecializer spec(t.info(), t.jsgraph(), const_context); | 141   JSContextSpecializer spec(t.info(), t.jsgraph(), const_context); | 
| 141 | 142 | 
| 142   { | 143   { | 
| 143     // Mutable slot, constant context, depth = 0 => do nothing. | 144     // Mutable slot, constant context, depth = 0 => do nothing. | 
| 144     Node* load = t.NewNode(t.javascript()->StoreContext(0, 0), const_context, | 145     Node* load = t.NewNode(t.javascript()->StoreContext(ContextAccess(0, 0)), | 
| 145                            const_context, start); | 146                            const_context, const_context, start); | 
| 146     Reduction r = spec.ReduceJSStoreContext(load); | 147     Reduction r = spec.ReduceJSStoreContext(load); | 
| 147     CHECK(!r.Changed()); | 148     CHECK(!r.Changed()); | 
| 148   } | 149   } | 
| 149 | 150 | 
| 150   { | 151   { | 
| 151     // Mutable slot, non-constant context, depth = 0 => do nothing. | 152     // Mutable slot, non-constant context, depth = 0 => do nothing. | 
| 152     Node* load = t.NewNode(t.javascript()->StoreContext(0, 0), param_context, | 153     Node* load = t.NewNode(t.javascript()->StoreContext(ContextAccess(0, 0)), | 
| 153                            param_context, start); | 154                            param_context, param_context, start); | 
| 154     Reduction r = spec.ReduceJSStoreContext(load); | 155     Reduction r = spec.ReduceJSStoreContext(load); | 
| 155     CHECK(!r.Changed()); | 156     CHECK(!r.Changed()); | 
| 156   } | 157   } | 
| 157 | 158 | 
| 158   { | 159   { | 
| 159     // Immutable slot, constant context, depth = 0 => do nothing. | 160     // Immutable slot, constant context, depth = 0 => do nothing. | 
| 160     Node* load = t.NewNode(t.javascript()->StoreContext(0, slot), const_context, | 161     Node* load = t.NewNode(t.javascript()->StoreContext(ContextAccess(0, slot)), | 
| 161                            const_context, start); | 162                            const_context, const_context, start); | 
| 162     Reduction r = spec.ReduceJSStoreContext(load); | 163     Reduction r = spec.ReduceJSStoreContext(load); | 
| 163     CHECK(!r.Changed()); | 164     CHECK(!r.Changed()); | 
| 164   } | 165   } | 
| 165 | 166 | 
| 166   { | 167   { | 
| 167     // Mutable slot, constant context, depth > 0 => fold-in parent context. | 168     // Mutable slot, constant context, depth > 0 => fold-in parent context. | 
| 168     Node* load = t.NewNode( | 169     Node* load = t.NewNode(t.javascript()->StoreContext(ContextAccess( | 
| 169         t.javascript()->StoreContext(2, Context::GLOBAL_EVAL_FUN_INDEX), | 170                                2, Context::GLOBAL_EVAL_FUN_INDEX)), | 
| 170         deep_const_context, deep_const_context, start); | 171                            deep_const_context, deep_const_context, start); | 
| 171     Reduction r = spec.ReduceJSStoreContext(load); | 172     Reduction r = spec.ReduceJSStoreContext(load); | 
| 172     CHECK(r.Changed()); | 173     CHECK(r.Changed()); | 
| 173     Node* new_context_input = NodeProperties::GetValueInput(r.replacement(), 0); | 174     Node* new_context_input = NodeProperties::GetValueInput(r.replacement(), 0); | 
| 174     CHECK_EQ(IrOpcode::kHeapConstant, new_context_input->opcode()); | 175     CHECK_EQ(IrOpcode::kHeapConstant, new_context_input->opcode()); | 
| 175     HeapObjectMatcher<Context> match(new_context_input); | 176     HeapObjectMatcher<Context> match(new_context_input); | 
| 176     CHECK_EQ(*native, *match.Value().handle()); | 177     CHECK_EQ(*native, *match.Value().handle()); | 
| 177     ContextAccess access = OpParameter<ContextAccess>(r.replacement()); | 178     ContextAccess access = OpParameter<ContextAccess>(r.replacement()); | 
| 178     CHECK_EQ(Context::GLOBAL_EVAL_FUN_INDEX, access.index()); | 179     CHECK_EQ(Context::GLOBAL_EVAL_FUN_INDEX, access.index()); | 
| 179     CHECK_EQ(0, access.depth()); | 180     CHECK_EQ(0, access.depth()); | 
| 180     CHECK_EQ(false, access.immutable()); | 181     CHECK_EQ(false, access.immutable()); | 
| (...skipping 21 matching lines...) Expand all  Loading... | 
| 202   t.info()->SetContext(native); | 203   t.info()->SetContext(native); | 
| 203 | 204 | 
| 204   Node* const_context = t.jsgraph()->Constant(native); | 205   Node* const_context = t.jsgraph()->Constant(native); | 
| 205   Node* param_context = t.NewNode(t.common()->Parameter(0), start); | 206   Node* param_context = t.NewNode(t.common()->Parameter(0), start); | 
| 206   JSContextSpecializer spec(t.info(), t.jsgraph(), const_context); | 207   JSContextSpecializer spec(t.info(), t.jsgraph(), const_context); | 
| 207 | 208 | 
| 208   { | 209   { | 
| 209     // Check that SpecializeToContext() replaces values and forwards effects | 210     // Check that SpecializeToContext() replaces values and forwards effects | 
| 210     // correctly, and folds values from constant and non-constant contexts | 211     // correctly, and folds values from constant and non-constant contexts | 
| 211     Node* effect_in = start; | 212     Node* effect_in = start; | 
| 212     Node* load = t.NewNode(t.javascript()->LoadContext(0, slot, true), | 213     Node* load = | 
| 213                            const_context, const_context, effect_in); | 214         t.NewNode(t.javascript()->LoadContext(ContextAccess(0, slot, true)), | 
|  | 215                   const_context, const_context, effect_in); | 
| 214 | 216 | 
| 215 | 217 | 
| 216     Node* value_use = t.NewNode(t.simplified()->ChangeTaggedToInt32(), load); | 218     Node* value_use = t.NewNode(t.simplified()->ChangeTaggedToInt32(), load); | 
| 217     Node* other_load = t.NewNode(t.javascript()->LoadContext(0, slot, true), | 219     Node* other_load = | 
| 218                                  param_context, param_context, load); | 220         t.NewNode(t.javascript()->LoadContext(ContextAccess(0, slot, true)), | 
|  | 221                   param_context, param_context, load); | 
| 219     Node* effect_use = other_load; | 222     Node* effect_use = other_load; | 
| 220     Node* other_use = | 223     Node* other_use = | 
| 221         t.NewNode(t.simplified()->ChangeTaggedToInt32(), other_load); | 224         t.NewNode(t.simplified()->ChangeTaggedToInt32(), other_load); | 
| 222 | 225 | 
| 223     Node* add = t.NewNode(t.javascript()->Add(), value_use, other_use, | 226     Node* add = t.NewNode(t.javascript()->Add(), value_use, other_use, | 
| 224                           param_context, other_load, start); | 227                           param_context, other_load, start); | 
| 225 | 228 | 
| 226     Node* ret = t.NewNode(t.common()->Return(), add, effect_use, start); | 229     Node* ret = t.NewNode(t.common()->Return(), add, effect_use, start); | 
| 227     Node* end = t.NewNode(t.common()->End(), ret); | 230     Node* end = t.NewNode(t.common()->End(), ret); | 
| 228     USE(end); | 231     USE(end); | 
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 298   { | 301   { | 
| 299     FunctionTester T( | 302     FunctionTester T( | 
| 300         "(function() { if (false) { var x = 1; } function inc(a)" | 303         "(function() { if (false) { var x = 1; } function inc(a)" | 
| 301         " { return a + x; } return inc; })()");  // x is undefined! | 304         " { return a + x; } return inc; })()");  // x is undefined! | 
| 302 | 305 | 
| 303     CHECK(T.Call(T.Val(0.0), T.Val(0.0)).ToHandleChecked()->IsNaN()); | 306     CHECK(T.Call(T.Val(0.0), T.Val(0.0)).ToHandleChecked()->IsNaN()); | 
| 304     CHECK(T.Call(T.Val(2.0), T.Val(0.0)).ToHandleChecked()->IsNaN()); | 307     CHECK(T.Call(T.Val(2.0), T.Val(0.0)).ToHandleChecked()->IsNaN()); | 
| 305     CHECK(T.Call(T.Val(-2.1), T.Val(0.0)).ToHandleChecked()->IsNaN()); | 308     CHECK(T.Call(T.Val(-2.1), T.Val(0.0)).ToHandleChecked()->IsNaN()); | 
| 306   } | 309   } | 
| 307 } | 310 } | 
| OLD | NEW | 
|---|