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/code-stubs.h"
6 #include "src/compiler/js-graph.h"
7 #include "src/compiler/node-properties.h"
8 #include "src/compiler/typer.h"
9 
10 namespace v8 {
11 namespace internal {
12 namespace compiler {
13 
14 #define CACHED(name, expr) \
15   cached_nodes_[name] ? cached_nodes_[name] : (cached_nodes_[name] = (expr))
16 
17 
CEntryStubConstant(int result_size)18 Node* JSGraph::CEntryStubConstant(int result_size) {
19   if (result_size == 1) {
20     return CACHED(kCEntryStubConstant,
21                   HeapConstant(CEntryStub(isolate(), 1).GetCode()));
22   }
23   return HeapConstant(CEntryStub(isolate(), result_size).GetCode());
24 }
25 
26 
EmptyFixedArrayConstant()27 Node* JSGraph::EmptyFixedArrayConstant() {
28   return CACHED(kEmptyFixedArrayConstant,
29                 HeapConstant(factory()->empty_fixed_array()));
30 }
31 
32 
UndefinedConstant()33 Node* JSGraph::UndefinedConstant() {
34   return CACHED(kUndefinedConstant, HeapConstant(factory()->undefined_value()));
35 }
36 
37 
TheHoleConstant()38 Node* JSGraph::TheHoleConstant() {
39   return CACHED(kTheHoleConstant, HeapConstant(factory()->the_hole_value()));
40 }
41 
42 
TrueConstant()43 Node* JSGraph::TrueConstant() {
44   return CACHED(kTrueConstant, HeapConstant(factory()->true_value()));
45 }
46 
47 
FalseConstant()48 Node* JSGraph::FalseConstant() {
49   return CACHED(kFalseConstant, HeapConstant(factory()->false_value()));
50 }
51 
52 
NullConstant()53 Node* JSGraph::NullConstant() {
54   return CACHED(kNullConstant, HeapConstant(factory()->null_value()));
55 }
56 
57 
ZeroConstant()58 Node* JSGraph::ZeroConstant() {
59   return CACHED(kZeroConstant, NumberConstant(0.0));
60 }
61 
62 
OneConstant()63 Node* JSGraph::OneConstant() {
64   return CACHED(kOneConstant, NumberConstant(1.0));
65 }
66 
67 
NaNConstant()68 Node* JSGraph::NaNConstant() {
69   return CACHED(kNaNConstant,
70                 NumberConstant(std::numeric_limits<double>::quiet_NaN()));
71 }
72 
73 
HeapConstant(Handle<HeapObject> value)74 Node* JSGraph::HeapConstant(Handle<HeapObject> value) {
75   if (value->IsConsString()) {
76     value = String::Flatten(Handle<String>::cast(value), TENURED);
77   }
78   Node** loc = cache_.FindHeapConstant(value);
79   if (*loc == nullptr) {
80     *loc = graph()->NewNode(common()->HeapConstant(value));
81   }
82   return *loc;
83 }
84 
85 
Constant(Handle<Object> value)86 Node* JSGraph::Constant(Handle<Object> value) {
87   // Dereference the handle to determine if a number constant or other
88   // canonicalized node can be used.
89   if (value->IsNumber()) {
90     return Constant(value->Number());
91   } else if (value->IsUndefined()) {
92     return UndefinedConstant();
93   } else if (value->IsTrue()) {
94     return TrueConstant();
95   } else if (value->IsFalse()) {
96     return FalseConstant();
97   } else if (value->IsNull()) {
98     return NullConstant();
99   } else if (value->IsTheHole()) {
100     return TheHoleConstant();
101   } else {
102     return HeapConstant(Handle<HeapObject>::cast(value));
103   }
104 }
105 
106 
Constant(double value)107 Node* JSGraph::Constant(double value) {
108   if (bit_cast<int64_t>(value) == bit_cast<int64_t>(0.0)) return ZeroConstant();
109   if (bit_cast<int64_t>(value) == bit_cast<int64_t>(1.0)) return OneConstant();
110   return NumberConstant(value);
111 }
112 
113 
Constant(int32_t value)114 Node* JSGraph::Constant(int32_t value) {
115   if (value == 0) return ZeroConstant();
116   if (value == 1) return OneConstant();
117   return NumberConstant(value);
118 }
119 
120 
Int32Constant(int32_t value)121 Node* JSGraph::Int32Constant(int32_t value) {
122   Node** loc = cache_.FindInt32Constant(value);
123   if (*loc == nullptr) {
124     *loc = graph()->NewNode(common()->Int32Constant(value));
125   }
126   return *loc;
127 }
128 
129 
Int64Constant(int64_t value)130 Node* JSGraph::Int64Constant(int64_t value) {
131   Node** loc = cache_.FindInt64Constant(value);
132   if (*loc == nullptr) {
133     *loc = graph()->NewNode(common()->Int64Constant(value));
134   }
135   return *loc;
136 }
137 
138 
NumberConstant(double value)139 Node* JSGraph::NumberConstant(double value) {
140   Node** loc = cache_.FindNumberConstant(value);
141   if (*loc == nullptr) {
142     *loc = graph()->NewNode(common()->NumberConstant(value));
143   }
144   return *loc;
145 }
146 
147 
Float32Constant(float value)148 Node* JSGraph::Float32Constant(float value) {
149   Node** loc = cache_.FindFloat32Constant(value);
150   if (*loc == nullptr) {
151     *loc = graph()->NewNode(common()->Float32Constant(value));
152   }
153   return *loc;
154 }
155 
156 
Float64Constant(double value)157 Node* JSGraph::Float64Constant(double value) {
158   Node** loc = cache_.FindFloat64Constant(value);
159   if (*loc == nullptr) {
160     *loc = graph()->NewNode(common()->Float64Constant(value));
161   }
162   return *loc;
163 }
164 
165 
ExternalConstant(ExternalReference reference)166 Node* JSGraph::ExternalConstant(ExternalReference reference) {
167   Node** loc = cache_.FindExternalConstant(reference);
168   if (*loc == nullptr) {
169     *loc = graph()->NewNode(common()->ExternalConstant(reference));
170   }
171   return *loc;
172 }
173 
174 
ExternalConstant(Runtime::FunctionId function_id)175 Node* JSGraph::ExternalConstant(Runtime::FunctionId function_id) {
176   return ExternalConstant(ExternalReference(function_id, isolate()));
177 }
178 
179 
EmptyFrameState()180 Node* JSGraph::EmptyFrameState() {
181   Node* empty_frame_state = cached_nodes_[kEmptyFrameState];
182   if (!empty_frame_state || empty_frame_state->IsDead()) {
183     Node* state_values = graph()->NewNode(common()->StateValues(0));
184     empty_frame_state = graph()->NewNode(
185         common()->FrameState(BailoutId::None(),
186                              OutputFrameStateCombine::Ignore(), nullptr),
187         state_values, state_values, state_values, NoContextConstant(),
188         UndefinedConstant(), graph()->start());
189     cached_nodes_[kEmptyFrameState] = empty_frame_state;
190   }
191   return empty_frame_state;
192 }
193 
194 
Dead()195 Node* JSGraph::Dead() {
196   return CACHED(kDead, graph()->NewNode(common()->Dead()));
197 }
198 
199 
GetCachedNodes(NodeVector * nodes)200 void JSGraph::GetCachedNodes(NodeVector* nodes) {
201   cache_.GetCachedNodes(nodes);
202   for (size_t i = 0; i < arraysize(cached_nodes_); i++) {
203     if (Node* node = cached_nodes_[i]) {
204       if (!node->IsDead()) nodes->push_back(node);
205     }
206   }
207 }
208 
209 }  // namespace compiler
210 }  // namespace internal
211 }  // namespace v8
212