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 Node* JSGraph::AllocateInNewSpaceStubConstant() { 18 return CACHED(kAllocateInNewSpaceStubConstant, 19 HeapConstant(isolate()->builtins()->AllocateInNewSpace())); 20 } 21 22 Node* JSGraph::AllocateInOldSpaceStubConstant() { 23 return CACHED(kAllocateInOldSpaceStubConstant, 24 HeapConstant(isolate()->builtins()->AllocateInOldSpace())); 25 } 26 27 Node* JSGraph::ToNumberBuiltinConstant() { 28 return CACHED(kToNumberBuiltinConstant, 29 HeapConstant(isolate()->builtins()->ToNumber())); 30 } 31 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 49 Node* JSGraph::EmptyFixedArrayConstant() { 50 return CACHED(kEmptyFixedArrayConstant, 51 HeapConstant(factory()->empty_fixed_array())); 52 } 53 54 Node* JSGraph::EmptyLiteralsArrayConstant() { 55 return CACHED(kEmptyLiteralsArrayConstant, 56 HeapConstant(factory()->empty_literals_array())); 57 } 58 59 Node* JSGraph::EmptyStringConstant() { 60 return CACHED(kEmptyStringConstant, HeapConstant(factory()->empty_string())); 61 } 62 63 Node* JSGraph::FixedArrayMapConstant() { 64 return CACHED(kFixedArrayMapConstant, 65 HeapConstant(factory()->fixed_array_map())); 66 } 67 68 Node* JSGraph::FixedDoubleArrayMapConstant() { 69 return CACHED(kFixedDoubleArrayMapConstant, 70 HeapConstant(factory()->fixed_double_array_map())); 71 } 72 73 Node* JSGraph::HeapNumberMapConstant() { 74 return CACHED(kHeapNumberMapConstant, 75 HeapConstant(factory()->heap_number_map())); 76 } 77 78 Node* JSGraph::OptimizedOutConstant() { 79 return CACHED(kOptimizedOutConstant, 80 HeapConstant(factory()->optimized_out())); 81 } 82 83 Node* JSGraph::StaleRegisterConstant() { 84 return CACHED(kStaleRegisterConstant, 85 HeapConstant(factory()->stale_register())); 86 } 87 88 Node* JSGraph::UndefinedConstant() { 89 return CACHED(kUndefinedConstant, HeapConstant(factory()->undefined_value())); 90 } 91 92 93 Node* JSGraph::TheHoleConstant() { 94 return CACHED(kTheHoleConstant, HeapConstant(factory()->the_hole_value())); 95 } 96 97 98 Node* JSGraph::TrueConstant() { 99 return CACHED(kTrueConstant, HeapConstant(factory()->true_value())); 100 } 101 102 103 Node* JSGraph::FalseConstant() { 104 return CACHED(kFalseConstant, HeapConstant(factory()->false_value())); 105 } 106 107 108 Node* JSGraph::NullConstant() { 109 return CACHED(kNullConstant, HeapConstant(factory()->null_value())); 110 } 111 112 113 Node* JSGraph::ZeroConstant() { 114 return CACHED(kZeroConstant, NumberConstant(0.0)); 115 } 116 117 Node* JSGraph::OneConstant() { 118 return CACHED(kOneConstant, NumberConstant(1.0)); 119 } 120 121 122 Node* JSGraph::NaNConstant() { 123 return CACHED(kNaNConstant, 124 NumberConstant(std::numeric_limits<double>::quiet_NaN())); 125 } 126 127 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 262 Node* JSGraph::ExternalConstant(Runtime::FunctionId function_id) { 263 return ExternalConstant(ExternalReference(function_id, isolate())); 264 } 265 266 Node* JSGraph::EmptyStateValues() { 267 return CACHED(kEmptyStateValues, graph()->NewNode(common()->StateValues(0))); 268 } 269 270 Node* JSGraph::Dead() { 271 return CACHED(kDead, graph()->NewNode(common()->Dead())); 272 } 273 274 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