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