Home | History | Annotate | Download | only in src
      1 // Copyright 2011 the V8 project authors. All rights reserved.
      2 // Redistribution and use in source and binary forms, with or without
      3 // modification, are permitted provided that the following conditions are
      4 // met:
      5 //
      6 //     * Redistributions of source code must retain the above copyright
      7 //       notice, this list of conditions and the following disclaimer.
      8 //     * Redistributions in binary form must reproduce the above
      9 //       copyright notice, this list of conditions and the following
     10 //       disclaimer in the documentation and/or other materials provided
     11 //       with the distribution.
     12 //     * Neither the name of Google Inc. nor the names of its
     13 //       contributors may be used to endorse or promote products derived
     14 //       from this software without specific prior written permission.
     15 //
     16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 
     28 #include "v8.h"
     29 #include "lithium.h"
     30 
     31 namespace v8 {
     32 namespace internal {
     33 
     34 
     35 void LOperand::PrintTo(StringStream* stream) {
     36   LUnallocated* unalloc = NULL;
     37   switch (kind()) {
     38     case INVALID:
     39       stream->Add("(0)");
     40       break;
     41     case UNALLOCATED:
     42       unalloc = LUnallocated::cast(this);
     43       stream->Add("v%d", unalloc->virtual_register());
     44       switch (unalloc->policy()) {
     45         case LUnallocated::NONE:
     46           break;
     47         case LUnallocated::FIXED_REGISTER: {
     48           const char* register_name =
     49               Register::AllocationIndexToString(unalloc->fixed_index());
     50           stream->Add("(=%s)", register_name);
     51           break;
     52         }
     53         case LUnallocated::FIXED_DOUBLE_REGISTER: {
     54           const char* double_register_name =
     55               DoubleRegister::AllocationIndexToString(unalloc->fixed_index());
     56           stream->Add("(=%s)", double_register_name);
     57           break;
     58         }
     59         case LUnallocated::FIXED_SLOT:
     60           stream->Add("(=%dS)", unalloc->fixed_index());
     61           break;
     62         case LUnallocated::MUST_HAVE_REGISTER:
     63           stream->Add("(R)");
     64           break;
     65         case LUnallocated::WRITABLE_REGISTER:
     66           stream->Add("(WR)");
     67           break;
     68         case LUnallocated::SAME_AS_FIRST_INPUT:
     69           stream->Add("(1)");
     70           break;
     71         case LUnallocated::ANY:
     72           stream->Add("(-)");
     73           break;
     74       }
     75       break;
     76     case CONSTANT_OPERAND:
     77       stream->Add("[constant:%d]", index());
     78       break;
     79     case STACK_SLOT:
     80       stream->Add("[stack:%d]", index());
     81       break;
     82     case DOUBLE_STACK_SLOT:
     83       stream->Add("[double_stack:%d]", index());
     84       break;
     85     case REGISTER:
     86       stream->Add("[%s|R]", Register::AllocationIndexToString(index()));
     87       break;
     88     case DOUBLE_REGISTER:
     89       stream->Add("[%s|R]", DoubleRegister::AllocationIndexToString(index()));
     90       break;
     91     case ARGUMENT:
     92       stream->Add("[arg:%d]", index());
     93       break;
     94   }
     95 }
     96 
     97 #define DEFINE_OPERAND_CACHE(name, type)                      \
     98   name* name::cache = NULL;                                   \
     99   void name::SetUpCache() {                                   \
    100     if (cache) return;                                        \
    101     cache = new name[kNumCachedOperands];                     \
    102     for (int i = 0; i < kNumCachedOperands; i++) {            \
    103       cache[i].ConvertTo(type, i);                            \
    104     }                                                         \
    105   }                                                           \
    106 
    107 DEFINE_OPERAND_CACHE(LConstantOperand, CONSTANT_OPERAND)
    108 DEFINE_OPERAND_CACHE(LStackSlot,       STACK_SLOT)
    109 DEFINE_OPERAND_CACHE(LDoubleStackSlot, DOUBLE_STACK_SLOT)
    110 DEFINE_OPERAND_CACHE(LRegister,        REGISTER)
    111 DEFINE_OPERAND_CACHE(LDoubleRegister,  DOUBLE_REGISTER)
    112 
    113 #undef DEFINE_OPERAND_CACHE
    114 
    115 void LOperand::SetUpCaches() {
    116   LConstantOperand::SetUpCache();
    117   LStackSlot::SetUpCache();
    118   LDoubleStackSlot::SetUpCache();
    119   LRegister::SetUpCache();
    120   LDoubleRegister::SetUpCache();
    121 }
    122 
    123 bool LParallelMove::IsRedundant() const {
    124   for (int i = 0; i < move_operands_.length(); ++i) {
    125     if (!move_operands_[i].IsRedundant()) return false;
    126   }
    127   return true;
    128 }
    129 
    130 
    131 void LParallelMove::PrintDataTo(StringStream* stream) const {
    132   bool first = true;
    133   for (int i = 0; i < move_operands_.length(); ++i) {
    134     if (!move_operands_[i].IsEliminated()) {
    135       LOperand* source = move_operands_[i].source();
    136       LOperand* destination = move_operands_[i].destination();
    137       if (!first) stream->Add(" ");
    138       first = false;
    139       if (source->Equals(destination)) {
    140         destination->PrintTo(stream);
    141       } else {
    142         destination->PrintTo(stream);
    143         stream->Add(" = ");
    144         source->PrintTo(stream);
    145       }
    146       stream->Add(";");
    147     }
    148   }
    149 }
    150 
    151 
    152 void LEnvironment::PrintTo(StringStream* stream) {
    153   stream->Add("[id=%d|", ast_id());
    154   stream->Add("[parameters=%d|", parameter_count());
    155   stream->Add("[arguments_stack_height=%d|", arguments_stack_height());
    156   for (int i = 0; i < values_.length(); ++i) {
    157     if (i != 0) stream->Add(";");
    158     if (values_[i] == NULL) {
    159       stream->Add("[hole]");
    160     } else {
    161       values_[i]->PrintTo(stream);
    162     }
    163   }
    164   stream->Add("]");
    165 }
    166 
    167 
    168 void LPointerMap::RecordPointer(LOperand* op) {
    169   // Do not record arguments as pointers.
    170   if (op->IsStackSlot() && op->index() < 0) return;
    171   ASSERT(!op->IsDoubleRegister() && !op->IsDoubleStackSlot());
    172   pointer_operands_.Add(op);
    173 }
    174 
    175 
    176 void LPointerMap::RemovePointer(LOperand* op) {
    177   // Do not record arguments as pointers.
    178   if (op->IsStackSlot() && op->index() < 0) return;
    179   ASSERT(!op->IsDoubleRegister() && !op->IsDoubleStackSlot());
    180   for (int i = 0; i < pointer_operands_.length(); ++i) {
    181     if (pointer_operands_[i]->Equals(op)) {
    182       pointer_operands_.Remove(i);
    183       --i;
    184     }
    185   }
    186 }
    187 
    188 
    189 void LPointerMap::RecordUntagged(LOperand* op) {
    190   // Do not record arguments as pointers.
    191   if (op->IsStackSlot() && op->index() < 0) return;
    192   ASSERT(!op->IsDoubleRegister() && !op->IsDoubleStackSlot());
    193   untagged_operands_.Add(op);
    194 }
    195 
    196 
    197 void LPointerMap::PrintTo(StringStream* stream) {
    198   stream->Add("{");
    199   for (int i = 0; i < pointer_operands_.length(); ++i) {
    200     if (i != 0) stream->Add(";");
    201     pointer_operands_[i]->PrintTo(stream);
    202   }
    203   stream->Add("} @%d", position());
    204 }
    205 
    206 
    207 int ElementsKindToShiftSize(ElementsKind elements_kind) {
    208   switch (elements_kind) {
    209     case EXTERNAL_BYTE_ELEMENTS:
    210     case EXTERNAL_PIXEL_ELEMENTS:
    211     case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
    212       return 0;
    213     case EXTERNAL_SHORT_ELEMENTS:
    214     case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
    215       return 1;
    216     case EXTERNAL_INT_ELEMENTS:
    217     case EXTERNAL_UNSIGNED_INT_ELEMENTS:
    218     case EXTERNAL_FLOAT_ELEMENTS:
    219       return 2;
    220     case EXTERNAL_DOUBLE_ELEMENTS:
    221     case FAST_DOUBLE_ELEMENTS:
    222       return 3;
    223     case FAST_SMI_ONLY_ELEMENTS:
    224     case FAST_ELEMENTS:
    225     case DICTIONARY_ELEMENTS:
    226     case NON_STRICT_ARGUMENTS_ELEMENTS:
    227       return kPointerSizeLog2;
    228   }
    229   UNREACHABLE();
    230   return 0;
    231 }
    232 
    233 
    234 } }  // namespace v8::internal
    235