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