• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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