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 12namespace v8 { 13namespace internal { 14namespace compiler { 15 16#define CACHED(name, expr) \ 17 cached_nodes_[name] ? cached_nodes_[name] : (cached_nodes_[name] = (expr)) 18 19Node* JSGraph::AllocateInNewSpaceStubConstant() { 20 return CACHED(kAllocateInNewSpaceStubConstant, 21 HeapConstant(isolate()->builtins()->AllocateInNewSpace())); 22} 23 24Node* JSGraph::AllocateInOldSpaceStubConstant() { 25 return CACHED(kAllocateInOldSpaceStubConstant, 26 HeapConstant(isolate()->builtins()->AllocateInOldSpace())); 27} 28 29Node* JSGraph::ToNumberBuiltinConstant() { 30 return CACHED(kToNumberBuiltinConstant, 31 HeapConstant(isolate()->builtins()->ToNumber())); 32} 33 34Node* 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 66Node* JSGraph::EmptyFixedArrayConstant() { 67 return CACHED(kEmptyFixedArrayConstant, 68 HeapConstant(factory()->empty_fixed_array())); 69} 70 71Node* JSGraph::EmptyStringConstant() { 72 return CACHED(kEmptyStringConstant, HeapConstant(factory()->empty_string())); 73} 74 75Node* JSGraph::FixedArrayMapConstant() { 76 return CACHED(kFixedArrayMapConstant, 77 HeapConstant(factory()->fixed_array_map())); 78} 79 80Node* JSGraph::FixedDoubleArrayMapConstant() { 81 return CACHED(kFixedDoubleArrayMapConstant, 82 HeapConstant(factory()->fixed_double_array_map())); 83} 84 85Node* JSGraph::HeapNumberMapConstant() { 86 return CACHED(kHeapNumberMapConstant, 87 HeapConstant(factory()->heap_number_map())); 88} 89 90Node* JSGraph::OptimizedOutConstant() { 91 return CACHED(kOptimizedOutConstant, 92 HeapConstant(factory()->optimized_out())); 93} 94 95Node* JSGraph::StaleRegisterConstant() { 96 return CACHED(kStaleRegisterConstant, 97 HeapConstant(factory()->stale_register())); 98} 99 100Node* JSGraph::UndefinedConstant() { 101 return CACHED(kUndefinedConstant, HeapConstant(factory()->undefined_value())); 102} 103 104 105Node* JSGraph::TheHoleConstant() { 106 return CACHED(kTheHoleConstant, HeapConstant(factory()->the_hole_value())); 107} 108 109 110Node* JSGraph::TrueConstant() { 111 return CACHED(kTrueConstant, HeapConstant(factory()->true_value())); 112} 113 114 115Node* JSGraph::FalseConstant() { 116 return CACHED(kFalseConstant, HeapConstant(factory()->false_value())); 117} 118 119 120Node* JSGraph::NullConstant() { 121 return CACHED(kNullConstant, HeapConstant(factory()->null_value())); 122} 123 124 125Node* JSGraph::ZeroConstant() { 126 return CACHED(kZeroConstant, NumberConstant(0.0)); 127} 128 129Node* JSGraph::OneConstant() { 130 return CACHED(kOneConstant, NumberConstant(1.0)); 131} 132 133 134Node* JSGraph::NaNConstant() { 135 return CACHED(kNaNConstant, 136 NumberConstant(std::numeric_limits<double>::quiet_NaN())); 137} 138 139 140Node* 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 149Node* 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 170Node* 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 177Node* JSGraph::Constant(int32_t value) { 178 if (value == 0) return ZeroConstant(); 179 if (value == 1) return OneConstant(); 180 return NumberConstant(value); 181} 182 183Node* JSGraph::Constant(uint32_t value) { 184 if (value == 0) return ZeroConstant(); 185 if (value == 1) return OneConstant(); 186 return NumberConstant(value); 187} 188 189Node* 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 198Node* 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 206Node* 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 215Node* 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 224Node* 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 231Node* 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 240Node* 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 249Node* 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 257Node* 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 265Node* 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 274Node* JSGraph::ExternalConstant(Runtime::FunctionId function_id) { 275 return ExternalConstant(ExternalReference(function_id, isolate())); 276} 277 278Node* JSGraph::EmptyStateValues() { 279 return CACHED(kEmptyStateValues, graph()->NewNode(common()->StateValues( 280 0, SparseInputMask::Dense()))); 281} 282 283Node* JSGraph::Dead() { 284 return CACHED(kDead, graph()->NewNode(common()->Dead())); 285} 286 287 288void 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