• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
5 #include "src/compiler/js-context-specialization.h"
6 
7 #include "src/compiler/common-operator.h"
8 #include "src/compiler/js-graph.h"
9 #include "src/compiler/js-operator.h"
10 #include "src/compiler/node-matchers.h"
11 #include "src/compiler/node-properties.h"
12 #include "src/contexts.h"
13 #include "src/objects-inl.h"
14 
15 namespace v8 {
16 namespace internal {
17 namespace compiler {
18 
Reduce(Node * node)19 Reduction JSContextSpecialization::Reduce(Node* node) {
20   switch (node->opcode()) {
21     case IrOpcode::kJSLoadContext:
22       return ReduceJSLoadContext(node);
23     case IrOpcode::kJSStoreContext:
24       return ReduceJSStoreContext(node);
25     default:
26       break;
27   }
28   return NoChange();
29 }
30 
31 
GetSpecializationContext(Node * node)32 MaybeHandle<Context> JSContextSpecialization::GetSpecializationContext(
33     Node* node) {
34   DCHECK(node->opcode() == IrOpcode::kJSLoadContext ||
35          node->opcode() == IrOpcode::kJSStoreContext);
36   Node* const object = NodeProperties::GetValueInput(node, 0);
37   return NodeProperties::GetSpecializationContext(object, context());
38 }
39 
40 
ReduceJSLoadContext(Node * node)41 Reduction JSContextSpecialization::ReduceJSLoadContext(Node* node) {
42   DCHECK_EQ(IrOpcode::kJSLoadContext, node->opcode());
43 
44   // Get the specialization context from the node.
45   Handle<Context> context;
46   if (!GetSpecializationContext(node).ToHandle(&context)) return NoChange();
47 
48   // Find the right parent context.
49   const ContextAccess& access = ContextAccessOf(node->op());
50   for (size_t i = access.depth(); i > 0; --i) {
51     context = handle(context->previous(), isolate());
52   }
53 
54   // If the access itself is mutable, only fold-in the parent.
55   if (!access.immutable()) {
56     // The access does not have to look up a parent, nothing to fold.
57     if (access.depth() == 0) {
58       return NoChange();
59     }
60     const Operator* op = jsgraph_->javascript()->LoadContext(
61         0, access.index(), access.immutable());
62     node->ReplaceInput(0, jsgraph_->Constant(context));
63     NodeProperties::ChangeOp(node, op);
64     return Changed(node);
65   }
66   Handle<Object> value =
67       handle(context->get(static_cast<int>(access.index())), isolate());
68 
69   // Even though the context slot is immutable, the context might have escaped
70   // before the function to which it belongs has initialized the slot.
71   // We must be conservative and check if the value in the slot is currently the
72   // hole or undefined. If it is neither of these, then it must be initialized.
73   if (value->IsUndefined(isolate()) || value->IsTheHole(isolate())) {
74     return NoChange();
75   }
76 
77   // Success. The context load can be replaced with the constant.
78   // TODO(titzer): record the specialization for sharing code across multiple
79   // contexts that have the same value in the corresponding context slot.
80   Node* constant = jsgraph_->Constant(value);
81   ReplaceWithValue(node, constant);
82   return Replace(constant);
83 }
84 
85 
ReduceJSStoreContext(Node * node)86 Reduction JSContextSpecialization::ReduceJSStoreContext(Node* node) {
87   DCHECK_EQ(IrOpcode::kJSStoreContext, node->opcode());
88 
89   // Get the specialization context from the node.
90   Handle<Context> context;
91   if (!GetSpecializationContext(node).ToHandle(&context)) return NoChange();
92 
93   // The access does not have to look up a parent, nothing to fold.
94   const ContextAccess& access = ContextAccessOf(node->op());
95   if (access.depth() == 0) {
96     return NoChange();
97   }
98 
99   // Find the right parent context.
100   for (size_t i = access.depth(); i > 0; --i) {
101     context = handle(context->previous(), isolate());
102   }
103 
104   node->ReplaceInput(0, jsgraph_->Constant(context));
105   NodeProperties::ChangeOp(node, javascript()->StoreContext(0, access.index()));
106   return Changed(node);
107 }
108 
109 
isolate() const110 Isolate* JSContextSpecialization::isolate() const {
111   return jsgraph()->isolate();
112 }
113 
114 
javascript() const115 JSOperatorBuilder* JSContextSpecialization::javascript() const {
116   return jsgraph()->javascript();
117 }
118 
119 }  // namespace compiler
120 }  // namespace internal
121 }  // namespace v8
122