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