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/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