5 #include "src/compiler/js-context-specialization.h" 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/linkage.h" 11 #include "src/compiler/node-matchers.h" 12 #include "src/compiler/node-properties.h" 13 #include "src/contexts-inl.h" 19 Reduction JSContextSpecialization::Reduce(Node* node) {
20 switch (node->opcode()) {
21 case IrOpcode::kParameter:
22 return ReduceParameter(node);
23 case IrOpcode::kJSLoadContext:
24 return ReduceJSLoadContext(node);
25 case IrOpcode::kJSStoreContext:
26 return ReduceJSStoreContext(node);
33 Reduction JSContextSpecialization::ReduceParameter(Node* node) {
34 DCHECK_EQ(IrOpcode::kParameter, node->opcode());
35 int const index = ParameterIndexOf(node->op());
36 if (index == Linkage::kJSCallClosureParamIndex) {
38 Handle<JSFunction>
function;
39 if (closure().ToHandle(&
function)) {
40 Node* value = jsgraph()->HeapConstant(
function);
41 return Replace(value);
47 Reduction JSContextSpecialization::SimplifyJSLoadContext(Node* node,
50 DCHECK_EQ(IrOpcode::kJSLoadContext, node->opcode());
51 const ContextAccess& access = ContextAccessOf(node->op());
52 DCHECK_LE(new_depth, access.depth());
54 if (new_depth == access.depth() &&
55 new_context == NodeProperties::GetContextInput(node)) {
59 const Operator* op = jsgraph_->javascript()->LoadContext(
60 new_depth, access.index(), access.immutable());
61 NodeProperties::ReplaceContextInput(node, new_context);
62 NodeProperties::ChangeOp(node, op);
66 Reduction JSContextSpecialization::SimplifyJSStoreContext(Node* node,
69 DCHECK_EQ(IrOpcode::kJSStoreContext, node->opcode());
70 const ContextAccess& access = ContextAccessOf(node->op());
71 DCHECK_LE(new_depth, access.depth());
73 if (new_depth == access.depth() &&
74 new_context == NodeProperties::GetContextInput(node)) {
79 jsgraph_->javascript()->StoreContext(new_depth, access.index());
80 NodeProperties::ReplaceContextInput(node, new_context);
81 NodeProperties::ChangeOp(node, op);
87 bool IsContextParameter(Node* node) {
88 DCHECK_EQ(IrOpcode::kParameter, node->opcode());
89 Node*
const start = NodeProperties::GetValueInput(node, 0);
90 DCHECK_EQ(IrOpcode::kStart, start->opcode());
91 int const index = ParameterIndexOf(node->op());
95 return index == start->op()->ValueOutputCount() - 2;
102 base::Optional<ContextRef> GetSpecializationContext(
103 JSHeapBroker* broker, Node* node,
size_t* distance,
104 Maybe<OuterContext> maybe_outer) {
105 switch (node->opcode()) {
106 case IrOpcode::kHeapConstant: {
107 HeapObjectRef object(broker, HeapConstantOf(node->op()));
108 if (
object.IsContext())
return object.AsContext();
111 case IrOpcode::kParameter: {
113 if (maybe_outer.To(&outer) && IsContextParameter(node) &&
114 *distance >= outer.distance) {
115 *distance -= outer.distance;
116 return ContextRef(broker, outer.context);
123 return base::Optional<ContextRef>();
128 Reduction JSContextSpecialization::ReduceJSLoadContext(Node* node) {
129 DCHECK_EQ(IrOpcode::kJSLoadContext, node->opcode());
131 const ContextAccess& access = ContextAccessOf(node->op());
132 size_t depth = access.depth();
135 Node* context = NodeProperties::GetOuterContext(node, &depth);
137 base::Optional<ContextRef> maybe_concrete =
138 GetSpecializationContext(broker(), context, &depth, outer());
139 if (!maybe_concrete.has_value()) {
142 return SimplifyJSLoadContext(node, context, depth);
146 ContextRef concrete = maybe_concrete.value();
147 concrete.Serialize();
148 for (; depth > 0; --depth) {
149 concrete = concrete.previous();
152 if (!access.immutable()) {
155 return SimplifyJSLoadContext(node, jsgraph()->Constant(concrete), depth);
159 base::Optional<ObjectRef> maybe_value;
161 maybe_value = concrete.get(static_cast<int>(access.index()));
162 if (maybe_value.has_value() && !maybe_value->IsSmi()) {
168 OddballType oddball_type = maybe_value->AsHeapObject().map().oddball_type();
169 if (oddball_type == OddballType::kUndefined ||
170 oddball_type == OddballType::kHole) {
175 if (!maybe_value.has_value()) {
176 return SimplifyJSLoadContext(node, jsgraph()->Constant(concrete), depth);
183 Node* constant = jsgraph_->Constant(*maybe_value);
184 ReplaceWithValue(node, constant);
185 return Replace(constant);
189 Reduction JSContextSpecialization::ReduceJSStoreContext(Node* node) {
190 DCHECK_EQ(IrOpcode::kJSStoreContext, node->opcode());
192 const ContextAccess& access = ContextAccessOf(node->op());
193 size_t depth = access.depth();
197 Node* context = NodeProperties::GetOuterContext(node, &depth);
199 base::Optional<ContextRef> maybe_concrete =
200 GetSpecializationContext(broker(), context, &depth, outer());
201 if (!maybe_concrete.has_value()) {
204 return SimplifyJSStoreContext(node, context, depth);
208 ContextRef concrete = maybe_concrete.value();
209 concrete.Serialize();
210 for (; depth > 0; --depth) {
211 concrete = concrete.previous();
214 return SimplifyJSStoreContext(node, jsgraph()->Constant(concrete), depth);
218 Isolate* JSContextSpecialization::isolate()
const {
219 return jsgraph()->isolate();