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-graph.h"
6
7 #include "src/code-stubs.h"
8 #include "src/compiler/node-properties.h"
9 #include "src/compiler/typer.h"
10 #include "src/objects-inl.h"
11
12 namespace v8 {
13 namespace internal {
14 namespace compiler {
15
16 #define CACHED(name, expr) \
17 cached_nodes_[name] ? cached_nodes_[name] : (cached_nodes_[name] = (expr))
18
AllocateInNewSpaceStubConstant()19 Node* JSGraph::AllocateInNewSpaceStubConstant() {
20 return CACHED(kAllocateInNewSpaceStubConstant,
21 HeapConstant(isolate()->builtins()->AllocateInNewSpace()));
22 }
23
AllocateInOldSpaceStubConstant()24 Node* JSGraph::AllocateInOldSpaceStubConstant() {
25 return CACHED(kAllocateInOldSpaceStubConstant,
26 HeapConstant(isolate()->builtins()->AllocateInOldSpace()));
27 }
28
ToNumberBuiltinConstant()29 Node* JSGraph::ToNumberBuiltinConstant() {
30 return CACHED(kToNumberBuiltinConstant,
31 HeapConstant(isolate()->builtins()->ToNumber()));
32 }
33
CEntryStubConstant(int result_size,SaveFPRegsMode save_doubles,ArgvMode argv_mode,bool builtin_exit_frame)34 Node* JSGraph::CEntryStubConstant(int result_size, SaveFPRegsMode save_doubles,
35 ArgvMode argv_mode, bool builtin_exit_frame) {
36 if (save_doubles == kDontSaveFPRegs && argv_mode == kArgvOnStack) {
37 DCHECK(result_size >= 1 && result_size <= 3);
38 if (!builtin_exit_frame) {
39 CachedNode key;
40 if (result_size == 1) {
41 key = kCEntryStub1Constant;
42 } else if (result_size == 2) {
43 key = kCEntryStub2Constant;
44 } else {
45 DCHECK(result_size == 3);
46 key = kCEntryStub3Constant;
47 }
48 return CACHED(
49 key, HeapConstant(CEntryStub(isolate(), result_size, save_doubles,
50 argv_mode, builtin_exit_frame)
51 .GetCode()));
52 }
53 CachedNode key = builtin_exit_frame
54 ? kCEntryStub1WithBuiltinExitFrameConstant
55 : kCEntryStub1Constant;
56 return CACHED(key,
57 HeapConstant(CEntryStub(isolate(), result_size, save_doubles,
58 argv_mode, builtin_exit_frame)
59 .GetCode()));
60 }
61 CEntryStub stub(isolate(), result_size, save_doubles, argv_mode,
62 builtin_exit_frame);
63 return HeapConstant(stub.GetCode());
64 }
65
EmptyFixedArrayConstant()66 Node* JSGraph::EmptyFixedArrayConstant() {
67 return CACHED(kEmptyFixedArrayConstant,
68 HeapConstant(factory()->empty_fixed_array()));
69 }
70
EmptyStringConstant()71 Node* JSGraph::EmptyStringConstant() {
72 return CACHED(kEmptyStringConstant, HeapConstant(factory()->empty_string()));
73 }
74
FixedArrayMapConstant()75 Node* JSGraph::FixedArrayMapConstant() {
76 return CACHED(kFixedArrayMapConstant,
77 HeapConstant(factory()->fixed_array_map()));
78 }
79
FixedDoubleArrayMapConstant()80 Node* JSGraph::FixedDoubleArrayMapConstant() {
81 return CACHED(kFixedDoubleArrayMapConstant,
82 HeapConstant(factory()->fixed_double_array_map()));
83 }
84
HeapNumberMapConstant()85 Node* JSGraph::HeapNumberMapConstant() {
86 return CACHED(kHeapNumberMapConstant,
87 HeapConstant(factory()->heap_number_map()));
88 }
89
OptimizedOutConstant()90 Node* JSGraph::OptimizedOutConstant() {
91 return CACHED(kOptimizedOutConstant,
92 HeapConstant(factory()->optimized_out()));
93 }
94
StaleRegisterConstant()95 Node* JSGraph::StaleRegisterConstant() {
96 return CACHED(kStaleRegisterConstant,
97 HeapConstant(factory()->stale_register()));
98 }
99
UndefinedConstant()100 Node* JSGraph::UndefinedConstant() {
101 return CACHED(kUndefinedConstant, HeapConstant(factory()->undefined_value()));
102 }
103
104
TheHoleConstant()105 Node* JSGraph::TheHoleConstant() {
106 return CACHED(kTheHoleConstant, HeapConstant(factory()->the_hole_value()));
107 }
108
109
TrueConstant()110 Node* JSGraph::TrueConstant() {
111 return CACHED(kTrueConstant, HeapConstant(factory()->true_value()));
112 }
113
114
FalseConstant()115 Node* JSGraph::FalseConstant() {
116 return CACHED(kFalseConstant, HeapConstant(factory()->false_value()));
117 }
118
119
NullConstant()120 Node* JSGraph::NullConstant() {
121 return CACHED(kNullConstant, HeapConstant(factory()->null_value()));
122 }
123
124
ZeroConstant()125 Node* JSGraph::ZeroConstant() {
126 return CACHED(kZeroConstant, NumberConstant(0.0));
127 }
128
OneConstant()129 Node* JSGraph::OneConstant() {
130 return CACHED(kOneConstant, NumberConstant(1.0));
131 }
132
133
NaNConstant()134 Node* JSGraph::NaNConstant() {
135 return CACHED(kNaNConstant,
136 NumberConstant(std::numeric_limits<double>::quiet_NaN()));
137 }
138
139
HeapConstant(Handle<HeapObject> value)140 Node* JSGraph::HeapConstant(Handle<HeapObject> value) {
141 Node** loc = cache_.FindHeapConstant(value);
142 if (*loc == nullptr) {
143 *loc = graph()->NewNode(common()->HeapConstant(value));
144 }
145 return *loc;
146 }
147
148
Constant(Handle<Object> value)149 Node* JSGraph::Constant(Handle<Object> value) {
150 // Dereference the handle to determine if a number constant or other
151 // canonicalized node can be used.
152 if (value->IsNumber()) {
153 return Constant(value->Number());
154 } else if (value->IsUndefined(isolate())) {
155 return UndefinedConstant();
156 } else if (value->IsTrue(isolate())) {
157 return TrueConstant();
158 } else if (value->IsFalse(isolate())) {
159 return FalseConstant();
160 } else if (value->IsNull(isolate())) {
161 return NullConstant();
162 } else if (value->IsTheHole(isolate())) {
163 return TheHoleConstant();
164 } else {
165 return HeapConstant(Handle<HeapObject>::cast(value));
166 }
167 }
168
169
Constant(double value)170 Node* JSGraph::Constant(double value) {
171 if (bit_cast<int64_t>(value) == bit_cast<int64_t>(0.0)) return ZeroConstant();
172 if (bit_cast<int64_t>(value) == bit_cast<int64_t>(1.0)) return OneConstant();
173 return NumberConstant(value);
174 }
175
176
Constant(int32_t value)177 Node* JSGraph::Constant(int32_t value) {
178 if (value == 0) return ZeroConstant();
179 if (value == 1) return OneConstant();
180 return NumberConstant(value);
181 }
182
Constant(uint32_t value)183 Node* JSGraph::Constant(uint32_t value) {
184 if (value == 0) return ZeroConstant();
185 if (value == 1) return OneConstant();
186 return NumberConstant(value);
187 }
188
Int32Constant(int32_t value)189 Node* JSGraph::Int32Constant(int32_t value) {
190 Node** loc = cache_.FindInt32Constant(value);
191 if (*loc == nullptr) {
192 *loc = graph()->NewNode(common()->Int32Constant(value));
193 }
194 return *loc;
195 }
196
197
Int64Constant(int64_t value)198 Node* JSGraph::Int64Constant(int64_t value) {
199 Node** loc = cache_.FindInt64Constant(value);
200 if (*loc == nullptr) {
201 *loc = graph()->NewNode(common()->Int64Constant(value));
202 }
203 return *loc;
204 }
205
RelocatableInt32Constant(int32_t value,RelocInfo::Mode rmode)206 Node* JSGraph::RelocatableInt32Constant(int32_t value, RelocInfo::Mode rmode) {
207 Node** loc = cache_.FindRelocatableInt32Constant(
208 value, static_cast<RelocInfoMode>(rmode));
209 if (*loc == nullptr) {
210 *loc = graph()->NewNode(common()->RelocatableInt32Constant(value, rmode));
211 }
212 return *loc;
213 }
214
RelocatableInt64Constant(int64_t value,RelocInfo::Mode rmode)215 Node* JSGraph::RelocatableInt64Constant(int64_t value, RelocInfo::Mode rmode) {
216 Node** loc = cache_.FindRelocatableInt64Constant(
217 value, static_cast<RelocInfoMode>(rmode));
218 if (*loc == nullptr) {
219 *loc = graph()->NewNode(common()->RelocatableInt64Constant(value, rmode));
220 }
221 return *loc;
222 }
223
RelocatableIntPtrConstant(intptr_t value,RelocInfo::Mode rmode)224 Node* JSGraph::RelocatableIntPtrConstant(intptr_t value,
225 RelocInfo::Mode rmode) {
226 return kPointerSize == 8
227 ? RelocatableInt64Constant(value, rmode)
228 : RelocatableInt32Constant(static_cast<int>(value), rmode);
229 }
230
NumberConstant(double value)231 Node* JSGraph::NumberConstant(double value) {
232 Node** loc = cache_.FindNumberConstant(value);
233 if (*loc == nullptr) {
234 *loc = graph()->NewNode(common()->NumberConstant(value));
235 }
236 return *loc;
237 }
238
239
Float32Constant(float value)240 Node* JSGraph::Float32Constant(float value) {
241 Node** loc = cache_.FindFloat32Constant(value);
242 if (*loc == nullptr) {
243 *loc = graph()->NewNode(common()->Float32Constant(value));
244 }
245 return *loc;
246 }
247
248
Float64Constant(double value)249 Node* JSGraph::Float64Constant(double value) {
250 Node** loc = cache_.FindFloat64Constant(value);
251 if (*loc == nullptr) {
252 *loc = graph()->NewNode(common()->Float64Constant(value));
253 }
254 return *loc;
255 }
256
PointerConstant(intptr_t value)257 Node* JSGraph::PointerConstant(intptr_t value) {
258 Node** loc = cache_.FindPointerConstant(value);
259 if (*loc == nullptr) {
260 *loc = graph()->NewNode(common()->PointerConstant(value));
261 }
262 return *loc;
263 }
264
ExternalConstant(ExternalReference reference)265 Node* JSGraph::ExternalConstant(ExternalReference reference) {
266 Node** loc = cache_.FindExternalConstant(reference);
267 if (*loc == nullptr) {
268 *loc = graph()->NewNode(common()->ExternalConstant(reference));
269 }
270 return *loc;
271 }
272
273
ExternalConstant(Runtime::FunctionId function_id)274 Node* JSGraph::ExternalConstant(Runtime::FunctionId function_id) {
275 return ExternalConstant(ExternalReference(function_id, isolate()));
276 }
277
EmptyStateValues()278 Node* JSGraph::EmptyStateValues() {
279 return CACHED(kEmptyStateValues, graph()->NewNode(common()->StateValues(
280 0, SparseInputMask::Dense())));
281 }
282
Dead()283 Node* JSGraph::Dead() {
284 return CACHED(kDead, graph()->NewNode(common()->Dead()));
285 }
286
287
GetCachedNodes(NodeVector * nodes)288 void JSGraph::GetCachedNodes(NodeVector* nodes) {
289 cache_.GetCachedNodes(nodes);
290 for (size_t i = 0; i < arraysize(cached_nodes_); i++) {
291 if (Node* node = cached_nodes_[i]) {
292 if (!node->IsDead()) nodes->push_back(node);
293 }
294 }
295 }
296
297 } // namespace compiler
298 } // namespace internal
299 } // namespace v8
300