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 19 Node* JSGraph::AllocateInNewSpaceStubConstant() { 20 return CACHED(kAllocateInNewSpaceStubConstant, 21 HeapConstant(isolate()->builtins()->AllocateInNewSpace())); 22 } 23 24 Node* JSGraph::AllocateInOldSpaceStubConstant() { 25 return CACHED(kAllocateInOldSpaceStubConstant, 26 HeapConstant(isolate()->builtins()->AllocateInOldSpace())); 27 } 28 29 Node* JSGraph::ToNumberBuiltinConstant() { 30 return CACHED(kToNumberBuiltinConstant, 31 HeapConstant(isolate()->builtins()->ToNumber())); 32 } 33 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 66 Node* JSGraph::EmptyFixedArrayConstant() { 67 return CACHED(kEmptyFixedArrayConstant, 68 HeapConstant(factory()->empty_fixed_array())); 69 } 70 71 Node* JSGraph::EmptyStringConstant() { 72 return CACHED(kEmptyStringConstant, HeapConstant(factory()->empty_string())); 73 } 74 75 Node* JSGraph::FixedArrayMapConstant() { 76 return CACHED(kFixedArrayMapConstant, 77 HeapConstant(factory()->fixed_array_map())); 78 } 79 80 Node* JSGraph::FixedDoubleArrayMapConstant() { 81 return CACHED(kFixedDoubleArrayMapConstant, 82 HeapConstant(factory()->fixed_double_array_map())); 83 } 84 85 Node* JSGraph::HeapNumberMapConstant() { 86 return CACHED(kHeapNumberMapConstant, 87 HeapConstant(factory()->heap_number_map())); 88 } 89 90 Node* JSGraph::OptimizedOutConstant() { 91 return CACHED(kOptimizedOutConstant, 92 HeapConstant(factory()->optimized_out())); 93 } 94 95 Node* JSGraph::StaleRegisterConstant() { 96 return CACHED(kStaleRegisterConstant, 97 HeapConstant(factory()->stale_register())); 98 } 99 100 Node* JSGraph::UndefinedConstant() { 101 return CACHED(kUndefinedConstant, HeapConstant(factory()->undefined_value())); 102 } 103 104 105 Node* JSGraph::TheHoleConstant() { 106 return CACHED(kTheHoleConstant, HeapConstant(factory()->the_hole_value())); 107 } 108 109 110 Node* JSGraph::TrueConstant() { 111 return CACHED(kTrueConstant, HeapConstant(factory()->true_value())); 112 } 113 114 115 Node* JSGraph::FalseConstant() { 116 return CACHED(kFalseConstant, HeapConstant(factory()->false_value())); 117 } 118 119 120 Node* JSGraph::NullConstant() { 121 return CACHED(kNullConstant, HeapConstant(factory()->null_value())); 122 } 123 124 125 Node* JSGraph::ZeroConstant() { 126 return CACHED(kZeroConstant, NumberConstant(0.0)); 127 } 128 129 Node* JSGraph::OneConstant() { 130 return CACHED(kOneConstant, NumberConstant(1.0)); 131 } 132 133 134 Node* JSGraph::NaNConstant() { 135 return CACHED(kNaNConstant, 136 NumberConstant(std::numeric_limits<double>::quiet_NaN())); 137 } 138 139 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 274 Node* JSGraph::ExternalConstant(Runtime::FunctionId function_id) { 275 return ExternalConstant(ExternalReference(function_id, isolate())); 276 } 277 278 Node* JSGraph::EmptyStateValues() { 279 return CACHED(kEmptyStateValues, graph()->NewNode(common()->StateValues( 280 0, SparseInputMask::Dense()))); 281 } 282 283 Node* JSGraph::Dead() { 284 return CACHED(kDead, graph()->NewNode(common()->Dead())); 285 } 286 287 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