f49887d9d13d0237194c7d1686adac5832e9ce1a
[platform/framework/web/crosswalk.git] / src / v8 / src / lithium-codegen.cc
1 // Copyright 2013 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/v8.h"
6
7 #include "src/lithium-codegen.h"
8
9 #if V8_TARGET_ARCH_IA32
10 #include "src/ia32/lithium-ia32.h"
11 #include "src/ia32/lithium-codegen-ia32.h"
12 #elif V8_TARGET_ARCH_X64
13 #include "src/x64/lithium-x64.h"
14 #include "src/x64/lithium-codegen-x64.h"
15 #elif V8_TARGET_ARCH_ARM
16 #include "src/arm/lithium-arm.h"
17 #include "src/arm/lithium-codegen-arm.h"
18 #elif V8_TARGET_ARCH_ARM64
19 #include "src/arm64/lithium-arm64.h"
20 #include "src/arm64/lithium-codegen-arm64.h"
21 #elif V8_TARGET_ARCH_MIPS
22 #include "src/mips/lithium-mips.h"
23 #include "src/mips/lithium-codegen-mips.h"
24 #elif V8_TARGET_ARCH_X87
25 #include "src/x87/lithium-x87.h"
26 #include "src/x87/lithium-codegen-x87.h"
27 #else
28 #error Unsupported target architecture.
29 #endif
30
31 namespace v8 {
32 namespace internal {
33
34
35 HGraph* LCodeGenBase::graph() const {
36   return chunk()->graph();
37 }
38
39
40 LCodeGenBase::LCodeGenBase(LChunk* chunk,
41                            MacroAssembler* assembler,
42                            CompilationInfo* info)
43     : chunk_(static_cast<LPlatformChunk*>(chunk)),
44       masm_(assembler),
45       info_(info),
46       zone_(info->zone()),
47       status_(UNUSED),
48       current_block_(-1),
49       current_instruction_(-1),
50       instructions_(chunk->instructions()),
51       last_lazy_deopt_pc_(0) {
52 }
53
54
55 bool LCodeGenBase::GenerateBody() {
56   ASSERT(is_generating());
57   bool emit_instructions = true;
58   LCodeGen* codegen = static_cast<LCodeGen*>(this);
59   for (current_instruction_ = 0;
60        !is_aborted() && current_instruction_ < instructions_->length();
61        current_instruction_++) {
62     LInstruction* instr = instructions_->at(current_instruction_);
63
64     // Don't emit code for basic blocks with a replacement.
65     if (instr->IsLabel()) {
66       emit_instructions = !LLabel::cast(instr)->HasReplacement() &&
67           (!FLAG_unreachable_code_elimination ||
68            instr->hydrogen_value()->block()->IsReachable());
69       if (FLAG_code_comments && !emit_instructions) {
70         Comment(
71             ";;; <@%d,#%d> -------------------- B%d (unreachable/replaced) "
72             "--------------------",
73             current_instruction_,
74             instr->hydrogen_value()->id(),
75             instr->hydrogen_value()->block()->block_id());
76       }
77     }
78     if (!emit_instructions) continue;
79
80     if (FLAG_code_comments && instr->HasInterestingComment(codegen)) {
81       Comment(";;; <@%d,#%d> %s",
82               current_instruction_,
83               instr->hydrogen_value()->id(),
84               instr->Mnemonic());
85     }
86
87     GenerateBodyInstructionPre(instr);
88
89     HValue* value = instr->hydrogen_value();
90     if (!value->position().IsUnknown()) {
91       RecordAndWritePosition(
92         chunk()->graph()->SourcePositionToScriptPosition(value->position()));
93     }
94
95     instr->CompileToNative(codegen);
96
97     GenerateBodyInstructionPost(instr);
98   }
99   EnsureSpaceForLazyDeopt(Deoptimizer::patch_size());
100   last_lazy_deopt_pc_ = masm()->pc_offset();
101   return !is_aborted();
102 }
103
104
105 void LCodeGenBase::CheckEnvironmentUsage() {
106 #ifdef DEBUG
107   bool dead_block = false;
108   for (int i = 0; i < instructions_->length(); i++) {
109     LInstruction* instr = instructions_->at(i);
110     HValue* hval = instr->hydrogen_value();
111     if (instr->IsLabel()) dead_block = LLabel::cast(instr)->HasReplacement();
112     if (dead_block || !hval->block()->IsReachable()) continue;
113
114     HInstruction* hinstr = HInstruction::cast(hval);
115     if (!hinstr->CanDeoptimize() && instr->HasEnvironment()) {
116       V8_Fatal(__FILE__, __LINE__, "CanDeoptimize is wrong for %s (%s)\n",
117                hinstr->Mnemonic(), instr->Mnemonic());
118     }
119
120     if (instr->HasEnvironment() && !instr->environment()->has_been_used()) {
121       V8_Fatal(__FILE__, __LINE__, "unused environment for %s (%s)\n",
122                hinstr->Mnemonic(), instr->Mnemonic());
123     }
124   }
125 #endif
126 }
127
128
129 void LCodeGenBase::Comment(const char* format, ...) {
130   if (!FLAG_code_comments) return;
131   char buffer[4 * KB];
132   StringBuilder builder(buffer, ARRAY_SIZE(buffer));
133   va_list arguments;
134   va_start(arguments, format);
135   builder.AddFormattedList(format, arguments);
136   va_end(arguments);
137
138   // Copy the string before recording it in the assembler to avoid
139   // issues when the stack allocated buffer goes out of scope.
140   size_t length = builder.position();
141   Vector<char> copy = Vector<char>::New(static_cast<int>(length) + 1);
142   MemCopy(copy.start(), builder.Finalize(), copy.length());
143   masm()->RecordComment(copy.start());
144 }
145
146
147 int LCodeGenBase::GetNextEmittedBlock() const {
148   for (int i = current_block_ + 1; i < graph()->blocks()->length(); ++i) {
149     if (!graph()->blocks()->at(i)->IsReachable()) continue;
150     if (!chunk_->GetLabel(i)->HasReplacement()) return i;
151   }
152   return -1;
153 }
154
155
156 static void AddWeakObjectToCodeDependency(Isolate* isolate,
157                                           Handle<Object> object,
158                                           Handle<Code> code) {
159   Heap* heap = isolate->heap();
160   heap->EnsureWeakObjectToCodeTable();
161   Handle<DependentCode> dep(heap->LookupWeakObjectToCodeDependency(object));
162   dep = DependentCode::Insert(dep, DependentCode::kWeakCodeGroup, code);
163   heap->AddWeakObjectToCodeDependency(object, dep);
164 }
165
166
167 void LCodeGenBase::RegisterWeakObjectsInOptimizedCode(Handle<Code> code) {
168   ASSERT(code->is_optimized_code());
169   ZoneList<Handle<Map> > maps(1, zone());
170   ZoneList<Handle<JSObject> > objects(1, zone());
171   ZoneList<Handle<Cell> > cells(1, zone());
172   int mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
173                   RelocInfo::ModeMask(RelocInfo::CELL);
174   for (RelocIterator it(*code, mode_mask); !it.done(); it.next()) {
175     RelocInfo::Mode mode = it.rinfo()->rmode();
176     if (mode == RelocInfo::CELL &&
177         code->IsWeakObjectInOptimizedCode(it.rinfo()->target_cell())) {
178       Handle<Cell> cell(it.rinfo()->target_cell());
179       cells.Add(cell, zone());
180     } else if (mode == RelocInfo::EMBEDDED_OBJECT &&
181                code->IsWeakObjectInOptimizedCode(it.rinfo()->target_object())) {
182       if (it.rinfo()->target_object()->IsMap()) {
183         Handle<Map> map(Map::cast(it.rinfo()->target_object()));
184         maps.Add(map, zone());
185       } else if (it.rinfo()->target_object()->IsJSObject()) {
186         Handle<JSObject> object(JSObject::cast(it.rinfo()->target_object()));
187         objects.Add(object, zone());
188       } else if (it.rinfo()->target_object()->IsCell()) {
189         Handle<Cell> cell(Cell::cast(it.rinfo()->target_object()));
190         cells.Add(cell, zone());
191       }
192     }
193   }
194   if (FLAG_enable_ool_constant_pool) {
195     code->constant_pool()->set_weak_object_state(
196         ConstantPoolArray::WEAK_OBJECTS_IN_OPTIMIZED_CODE);
197   }
198 #ifdef VERIFY_HEAP
199   // This disables verification of weak embedded objects after full GC.
200   // AddDependentCode can cause a GC, which would observe the state where
201   // this code is not yet in the depended code lists of the embedded maps.
202   NoWeakObjectVerificationScope disable_verification_of_embedded_objects;
203 #endif
204   for (int i = 0; i < maps.length(); i++) {
205     Map::AddDependentCode(maps.at(i), DependentCode::kWeakCodeGroup, code);
206   }
207   for (int i = 0; i < objects.length(); i++) {
208     AddWeakObjectToCodeDependency(isolate(), objects.at(i), code);
209   }
210   for (int i = 0; i < cells.length(); i++) {
211     AddWeakObjectToCodeDependency(isolate(), cells.at(i), code);
212   }
213 }
214
215
216 void LCodeGenBase::Abort(BailoutReason reason) {
217   info()->set_bailout_reason(reason);
218   status_ = ABORTED;
219 }
220
221
222 void LCodeGenBase::AddDeprecationDependency(Handle<Map> map) {
223   if (map->is_deprecated()) return Abort(kMapBecameDeprecated);
224   chunk_->AddDeprecationDependency(map);
225 }
226
227
228 void LCodeGenBase::AddStabilityDependency(Handle<Map> map) {
229   if (!map->is_stable()) return Abort(kMapBecameUnstable);
230   chunk_->AddStabilityDependency(map);
231 }
232
233 } }  // namespace v8::internal