Home | History | Annotate | Download | only in compiler
      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