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