V8 Project
js-context-specialization.cc
Go to the documentation of this file.
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
3 // found in the LICENSE file.
4 
13 
14 namespace v8 {
15 namespace internal {
16 namespace compiler {
17 
19  public:
21  : spec_(spec) {}
22 
24  switch (node->opcode()) {
25  case IrOpcode::kJSLoadContext: {
26  Reduction r = spec_->ReduceJSLoadContext(node);
27  if (r.Changed() && r.replacement() != node) {
28  NodeProperties::ReplaceWithValue(node, r.replacement());
29  node->RemoveAllInputs();
30  }
31  break;
32  }
33  case IrOpcode::kJSStoreContext: {
34  Reduction r = spec_->ReduceJSStoreContext(node);
35  if (r.Changed() && r.replacement() != node) {
36  NodeProperties::ReplaceWithValue(node, r.replacement());
37  node->RemoveAllInputs();
38  }
39  break;
40  }
41  default:
42  break;
43  }
45  }
46 
47  private:
49 };
50 
51 
55 
56  ContextSpecializationVisitor visitor(this);
58 }
59 
60 
62  DCHECK_EQ(IrOpcode::kJSLoadContext, node->opcode());
63 
64  HeapObjectMatcher<Context> m(NodeProperties::GetValueInput(node, 0));
65  // If the context is not constant, no reduction can occur.
66  if (!m.HasValue()) {
67  return Reducer::NoChange();
68  }
69 
70  ContextAccess access = OpParameter<ContextAccess>(node);
71 
72  // Find the right parent context.
73  Context* context = *m.Value().handle();
74  for (int i = access.depth(); i > 0; --i) {
75  context = context->previous();
76  }
77 
78  // If the access itself is mutable, only fold-in the parent.
79  if (!access.immutable()) {
80  // The access does not have to look up a parent, nothing to fold.
81  if (access.depth() == 0) {
82  return Reducer::NoChange();
83  }
84  const Operator* op = jsgraph_->javascript()->LoadContext(
85  0, access.index(), access.immutable());
86  node->set_op(op);
87  Handle<Object> context_handle = Handle<Object>(context, info_->isolate());
88  node->ReplaceInput(0, jsgraph_->Constant(context_handle));
89  return Reducer::Changed(node);
90  }
91  Handle<Object> value =
92  Handle<Object>(context->get(access.index()), info_->isolate());
93 
94  // Even though the context slot is immutable, the context might have escaped
95  // before the function to which it belongs has initialized the slot.
96  // We must be conservative and check if the value in the slot is currently the
97  // hole or undefined. If it is neither of these, then it must be initialized.
98  if (value->IsUndefined() || value->IsTheHole()) {
99  return Reducer::NoChange();
100  }
101 
102  // Success. The context load can be replaced with the constant.
103  // TODO(titzer): record the specialization for sharing code across multiple
104  // contexts that have the same value in the corresponding context slot.
105  return Reducer::Replace(jsgraph_->Constant(value));
106 }
107 
108 
110  DCHECK_EQ(IrOpcode::kJSStoreContext, node->opcode());
111 
112  HeapObjectMatcher<Context> m(NodeProperties::GetValueInput(node, 0));
113  // If the context is not constant, no reduction can occur.
114  if (!m.HasValue()) {
115  return Reducer::NoChange();
116  }
117 
118  ContextAccess access = OpParameter<ContextAccess>(node);
119 
120  // The access does not have to look up a parent, nothing to fold.
121  if (access.depth() == 0) {
122  return Reducer::NoChange();
123  }
124 
125  // Find the right parent context.
126  Context* context = *m.Value().handle();
127  for (int i = access.depth(); i > 0; --i) {
128  context = context->previous();
129  }
130 
131  const Operator* op = jsgraph_->javascript()->StoreContext(0, access.index());
132  node->set_op(op);
133  Handle<Object> new_context_handle = Handle<Object>(context, info_->isolate());
134  node->ReplaceInput(0, jsgraph_->Constant(new_context_handle));
135 
136  return Reducer::Changed(node);
137 }
138 
139 } // namespace compiler
140 } // namespace internal
141 } // namespace v8
Handle< Context > context() const
Definition: compiler.h:127
Isolate * isolate() const
Definition: compiler.h:96
Context * previous()
Definition: contexts.h:419
Object * get(int index)
Definition: objects-inl.h:2165
void VisitNodeInputsFromEnd(Visitor *visitor)
Definition: graph-inl.h:30
JSOperatorBuilder * javascript()
Definition: js-graph.h:86
Node * Constant(Handle< Object > value)
Definition: js-graph.cc:115
const Operator * LoadContext(uint16_t depth, uint32_t index, bool immutable)
Definition: js-operator.h:152
const Operator * StoreContext(uint16_t depth, uint32_t index)
Definition: js-operator.h:157
static void ReplaceWithValue(Node *node, Node *value, Node *effect=NULL)
static Node * GetValueInput(Node *node, int index)
static Reduction Replace(Node *node)
Definition: graph-reducer.h:47
static Reduction Changed(Node *node)
Definition: graph-reducer.h:48
#define DCHECK_EQ(v1, v2)
Definition: logging.h:206
Debugger support for the V8 JavaScript engine.
Definition: accessors.cc:20