Home | History | Annotate | Download | only in src
      1 // Copyright 2013 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 
     30 #include "lithium-codegen.h"
     31 
     32 #if V8_TARGET_ARCH_IA32
     33 #include "ia32/lithium-ia32.h"
     34 #include "ia32/lithium-codegen-ia32.h"
     35 #elif V8_TARGET_ARCH_X64
     36 #include "x64/lithium-x64.h"
     37 #include "x64/lithium-codegen-x64.h"
     38 #elif V8_TARGET_ARCH_ARM
     39 #include "arm/lithium-arm.h"
     40 #include "arm/lithium-codegen-arm.h"
     41 #elif V8_TARGET_ARCH_MIPS
     42 #include "mips/lithium-mips.h"
     43 #include "mips/lithium-codegen-mips.h"
     44 #else
     45 #error Unsupported target architecture.
     46 #endif
     47 
     48 namespace v8 {
     49 namespace internal {
     50 
     51 
     52 HGraph* LCodeGenBase::graph() const {
     53   return chunk()->graph();
     54 }
     55 
     56 
     57 LCodeGenBase::LCodeGenBase(LChunk* chunk,
     58                            MacroAssembler* assembler,
     59                            CompilationInfo* info)
     60     : chunk_(static_cast<LPlatformChunk*>(chunk)),
     61       masm_(assembler),
     62       info_(info),
     63       zone_(info->zone()),
     64       status_(UNUSED),
     65       current_block_(-1),
     66       current_instruction_(-1),
     67       instructions_(chunk->instructions()),
     68       last_lazy_deopt_pc_(0) {
     69 }
     70 
     71 
     72 bool LCodeGenBase::GenerateBody() {
     73   ASSERT(is_generating());
     74   bool emit_instructions = true;
     75   LCodeGen* codegen = static_cast<LCodeGen*>(this);
     76   for (current_instruction_ = 0;
     77        !is_aborted() && current_instruction_ < instructions_->length();
     78        current_instruction_++) {
     79     LInstruction* instr = instructions_->at(current_instruction_);
     80 
     81     // Don't emit code for basic blocks with a replacement.
     82     if (instr->IsLabel()) {
     83       emit_instructions = !LLabel::cast(instr)->HasReplacement() &&
     84           (!FLAG_unreachable_code_elimination ||
     85            instr->hydrogen_value()->block()->IsReachable());
     86       if (FLAG_code_comments && !emit_instructions) {
     87         Comment(
     88             ";;; <@%d,#%d> -------------------- B%d (unreachable/replaced) "
     89             "--------------------",
     90             current_instruction_,
     91             instr->hydrogen_value()->id(),
     92             instr->hydrogen_value()->block()->block_id());
     93       }
     94     }
     95     if (!emit_instructions) continue;
     96 
     97     if (FLAG_code_comments && instr->HasInterestingComment(codegen)) {
     98       Comment(";;; <@%d,#%d> %s",
     99               current_instruction_,
    100               instr->hydrogen_value()->id(),
    101               instr->Mnemonic());
    102     }
    103 
    104     GenerateBodyInstructionPre(instr);
    105 
    106     HValue* value = instr->hydrogen_value();
    107     if (value->position() != RelocInfo::kNoPosition) {
    108       ASSERT(!graph()->info()->IsOptimizing() ||
    109              !FLAG_emit_opt_code_positions ||
    110              value->position() != RelocInfo::kNoPosition);
    111       RecordAndWritePosition(value->position());
    112     }
    113 
    114     instr->CompileToNative(codegen);
    115 
    116     GenerateBodyInstructionPost(instr);
    117   }
    118   EnsureSpaceForLazyDeopt(Deoptimizer::patch_size());
    119   last_lazy_deopt_pc_ = masm()->pc_offset();
    120   return !is_aborted();
    121 }
    122 
    123 
    124 void LCodeGenBase::Comment(const char* format, ...) {
    125   if (!FLAG_code_comments) return;
    126   char buffer[4 * KB];
    127   StringBuilder builder(buffer, ARRAY_SIZE(buffer));
    128   va_list arguments;
    129   va_start(arguments, format);
    130   builder.AddFormattedList(format, arguments);
    131   va_end(arguments);
    132 
    133   // Copy the string before recording it in the assembler to avoid
    134   // issues when the stack allocated buffer goes out of scope.
    135   size_t length = builder.position();
    136   Vector<char> copy = Vector<char>::New(static_cast<int>(length) + 1);
    137   OS::MemCopy(copy.start(), builder.Finalize(), copy.length());
    138   masm()->RecordComment(copy.start());
    139 }
    140 
    141 
    142 int LCodeGenBase::GetNextEmittedBlock() const {
    143   for (int i = current_block_ + 1; i < graph()->blocks()->length(); ++i) {
    144     if (!chunk_->GetLabel(i)->HasReplacement()) return i;
    145   }
    146   return -1;
    147 }
    148 
    149 
    150 void LCodeGenBase::RegisterDependentCodeForEmbeddedMaps(Handle<Code> code) {
    151   ZoneList<Handle<Map> > maps(1, zone());
    152   ZoneList<Handle<JSObject> > objects(1, zone());
    153   int mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
    154   for (RelocIterator it(*code, mode_mask); !it.done(); it.next()) {
    155     if (Code::IsWeakEmbeddedObject(code->kind(), it.rinfo()->target_object())) {
    156       if (it.rinfo()->target_object()->IsMap()) {
    157         Handle<Map> map(Map::cast(it.rinfo()->target_object()));
    158         maps.Add(map, zone());
    159       } else if (it.rinfo()->target_object()->IsJSObject()) {
    160         Handle<JSObject> object(JSObject::cast(it.rinfo()->target_object()));
    161         objects.Add(object, zone());
    162       }
    163     }
    164   }
    165 #ifdef VERIFY_HEAP
    166   // This disables verification of weak embedded objects after full GC.
    167   // AddDependentCode can cause a GC, which would observe the state where
    168   // this code is not yet in the depended code lists of the embedded maps.
    169   NoWeakObjectVerificationScope disable_verification_of_embedded_objects;
    170 #endif
    171   for (int i = 0; i < maps.length(); i++) {
    172     maps.at(i)->AddDependentCode(DependentCode::kWeaklyEmbeddedGroup, code);
    173   }
    174   for (int i = 0; i < objects.length(); i++) {
    175     AddWeakObjectToCodeDependency(isolate()->heap(), objects.at(i), code);
    176   }
    177 }
    178 
    179 
    180 } }  // namespace v8::internal
    181