V8 Project
lithium-codegen.cc
Go to the documentation of this file.
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" // NOLINT
11 #include "src/ia32/lithium-codegen-ia32.h" // NOLINT
12 #elif V8_TARGET_ARCH_X64
13 #include "src/x64/lithium-x64.h" // NOLINT
14 #include "src/x64/lithium-codegen-x64.h" // NOLINT
15 #elif V8_TARGET_ARCH_ARM
16 #include "src/arm/lithium-arm.h" // NOLINT
17 #include "src/arm/lithium-codegen-arm.h" // NOLINT
18 #elif V8_TARGET_ARCH_ARM64
19 #include "src/arm64/lithium-arm64.h" // NOLINT
20 #include "src/arm64/lithium-codegen-arm64.h" // NOLINT
21 #elif V8_TARGET_ARCH_MIPS
22 #include "src/mips/lithium-mips.h" // NOLINT
23 #include "src/mips/lithium-codegen-mips.h" // NOLINT
24 #elif V8_TARGET_ARCH_MIPS64
25 #include "src/mips64/lithium-mips64.h" // NOLINT
26 #include "src/mips64/lithium-codegen-mips64.h" // NOLINT
27 #elif V8_TARGET_ARCH_X87
28 #include "src/x87/lithium-x87.h" // NOLINT
29 #include "src/x87/lithium-codegen-x87.h" // NOLINT
30 #else
31 #error Unsupported target architecture.
32 #endif
33 
34 namespace v8 {
35 namespace internal {
36 
37 
38 HGraph* LCodeGenBase::graph() const {
39  return chunk()->graph();
40 }
41 
42 
43 LCodeGenBase::LCodeGenBase(LChunk* chunk,
44  MacroAssembler* assembler,
45  CompilationInfo* info)
46  : chunk_(static_cast<LPlatformChunk*>(chunk)),
47  masm_(assembler),
48  info_(info),
49  zone_(info->zone()),
50  status_(UNUSED),
51  current_block_(-1),
52  current_instruction_(-1),
53  instructions_(chunk->instructions()),
54  last_lazy_deopt_pc_(0) {
55 }
56 
57 
58 bool LCodeGenBase::GenerateBody() {
59  DCHECK(is_generating());
60  bool emit_instructions = true;
61  LCodeGen* codegen = static_cast<LCodeGen*>(this);
62  for (current_instruction_ = 0;
63  !is_aborted() && current_instruction_ < instructions_->length();
64  current_instruction_++) {
65  LInstruction* instr = instructions_->at(current_instruction_);
66 
67  // Don't emit code for basic blocks with a replacement.
68  if (instr->IsLabel()) {
69  emit_instructions = !LLabel::cast(instr)->HasReplacement() &&
70  (!FLAG_unreachable_code_elimination ||
71  instr->hydrogen_value()->block()->IsReachable());
72  if (FLAG_code_comments && !emit_instructions) {
73  Comment(
74  ";;; <@%d,#%d> -------------------- B%d (unreachable/replaced) "
75  "--------------------",
76  current_instruction_,
77  instr->hydrogen_value()->id(),
78  instr->hydrogen_value()->block()->block_id());
79  }
80  }
81  if (!emit_instructions) continue;
82 
83  if (FLAG_code_comments && instr->HasInterestingComment(codegen)) {
84  Comment(";;; <@%d,#%d> %s",
85  current_instruction_,
86  instr->hydrogen_value()->id(),
87  instr->Mnemonic());
88  }
89 
90  GenerateBodyInstructionPre(instr);
91 
92  HValue* value = instr->hydrogen_value();
93  if (!value->position().IsUnknown()) {
94  RecordAndWritePosition(
95  chunk()->graph()->SourcePositionToScriptPosition(value->position()));
96  }
97 
98  instr->CompileToNative(codegen);
99 
100  GenerateBodyInstructionPost(instr);
101  }
102  EnsureSpaceForLazyDeopt(Deoptimizer::patch_size());
103  last_lazy_deopt_pc_ = masm()->pc_offset();
104  return !is_aborted();
105 }
106 
107 
108 void LCodeGenBase::CheckEnvironmentUsage() {
109 #ifdef DEBUG
110  bool dead_block = false;
111  for (int i = 0; i < instructions_->length(); i++) {
112  LInstruction* instr = instructions_->at(i);
113  HValue* hval = instr->hydrogen_value();
114  if (instr->IsLabel()) dead_block = LLabel::cast(instr)->HasReplacement();
115  if (dead_block || !hval->block()->IsReachable()) continue;
116 
117  HInstruction* hinstr = HInstruction::cast(hval);
118  if (!hinstr->CanDeoptimize() && instr->HasEnvironment()) {
119  V8_Fatal(__FILE__, __LINE__, "CanDeoptimize is wrong for %s (%s)",
120  hinstr->Mnemonic(), instr->Mnemonic());
121  }
122 
123  if (instr->HasEnvironment() && !instr->environment()->has_been_used()) {
124  V8_Fatal(__FILE__, __LINE__, "unused environment for %s (%s)",
125  hinstr->Mnemonic(), instr->Mnemonic());
126  }
127  }
128 #endif
129 }
130 
131 
132 void LCodeGenBase::Comment(const char* format, ...) {
133  if (!FLAG_code_comments) return;
134  char buffer[4 * KB];
135  StringBuilder builder(buffer, arraysize(buffer));
136  va_list arguments;
137  va_start(arguments, format);
138  builder.AddFormattedList(format, arguments);
139  va_end(arguments);
140 
141  // Copy the string before recording it in the assembler to avoid
142  // issues when the stack allocated buffer goes out of scope.
143  size_t length = builder.position();
144  Vector<char> copy = Vector<char>::New(static_cast<int>(length) + 1);
145  MemCopy(copy.start(), builder.Finalize(), copy.length());
146  masm()->RecordComment(copy.start());
147 }
148 
149 
150 void LCodeGenBase::DeoptComment(const Deoptimizer::Reason& reason) {
151  OStringStream os;
152  os << ";;; deoptimize at " << HSourcePosition(reason.raw_position) << " "
153  << reason.mnemonic;
154  if (reason.detail != NULL) os << ": " << reason.detail;
155  Comment("%s", os.c_str());
156 }
157 
158 
159 int LCodeGenBase::GetNextEmittedBlock() const {
160  for (int i = current_block_ + 1; i < graph()->blocks()->length(); ++i) {
161  if (!graph()->blocks()->at(i)->IsReachable()) continue;
162  if (!chunk_->GetLabel(i)->HasReplacement()) return i;
163  }
164  return -1;
165 }
166 
167 
169  Handle<Object> object,
170  Handle<Code> code) {
171  Heap* heap = isolate->heap();
174  dep = DependentCode::Insert(dep, DependentCode::kWeakCodeGroup, code);
175  heap->AddWeakObjectToCodeDependency(object, dep);
176 }
177 
178 
179 void LCodeGenBase::RegisterWeakObjectsInOptimizedCode(Handle<Code> code) {
180  DCHECK(code->is_optimized_code());
181  ZoneList<Handle<Map> > maps(1, zone());
182  ZoneList<Handle<JSObject> > objects(1, zone());
183  ZoneList<Handle<Cell> > cells(1, zone());
184  int mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
185  RelocInfo::ModeMask(RelocInfo::CELL);
186  for (RelocIterator it(*code, mode_mask); !it.done(); it.next()) {
187  RelocInfo::Mode mode = it.rinfo()->rmode();
188  if (mode == RelocInfo::CELL &&
189  code->IsWeakObjectInOptimizedCode(it.rinfo()->target_cell())) {
190  Handle<Cell> cell(it.rinfo()->target_cell());
191  cells.Add(cell, zone());
192  } else if (mode == RelocInfo::EMBEDDED_OBJECT &&
193  code->IsWeakObjectInOptimizedCode(it.rinfo()->target_object())) {
194  if (it.rinfo()->target_object()->IsMap()) {
195  Handle<Map> map(Map::cast(it.rinfo()->target_object()));
196  maps.Add(map, zone());
197  } else if (it.rinfo()->target_object()->IsJSObject()) {
198  Handle<JSObject> object(JSObject::cast(it.rinfo()->target_object()));
199  objects.Add(object, zone());
200  } else if (it.rinfo()->target_object()->IsCell()) {
201  Handle<Cell> cell(Cell::cast(it.rinfo()->target_object()));
202  cells.Add(cell, zone());
203  }
204  }
205  }
206  if (FLAG_enable_ool_constant_pool) {
207  code->constant_pool()->set_weak_object_state(
208  ConstantPoolArray::WEAK_OBJECTS_IN_OPTIMIZED_CODE);
209  }
210 #ifdef VERIFY_HEAP
211  // This disables verification of weak embedded objects after full GC.
212  // AddDependentCode can cause a GC, which would observe the state where
213  // this code is not yet in the depended code lists of the embedded maps.
214  NoWeakObjectVerificationScope disable_verification_of_embedded_objects;
215 #endif
216  for (int i = 0; i < maps.length(); i++) {
217  Map::AddDependentCode(maps.at(i), DependentCode::kWeakCodeGroup, code);
218  }
219  for (int i = 0; i < objects.length(); i++) {
220  AddWeakObjectToCodeDependency(isolate(), objects.at(i), code);
221  }
222  for (int i = 0; i < cells.length(); i++) {
223  AddWeakObjectToCodeDependency(isolate(), cells.at(i), code);
224  }
225 }
226 
227 
228 void LCodeGenBase::Abort(BailoutReason reason) {
229  info()->AbortOptimization(reason);
230  status_ = ABORTED;
231 }
232 
233 
234 void LCodeGenBase::Retry(BailoutReason reason) {
235  info()->RetryOptimization(reason);
236  status_ = ABORTED;
237 }
238 
239 
240 void LCodeGenBase::AddDeprecationDependency(Handle<Map> map) {
241  if (map->is_deprecated()) return Retry(kMapBecameDeprecated);
242  chunk_->AddDeprecationDependency(map);
243 }
244 
245 
246 void LCodeGenBase::AddStabilityDependency(Handle<Map> map) {
247  if (!map->is_stable()) return Retry(kMapBecameUnstable);
248  chunk_->AddStabilityDependency(map);
249 }
250 
251 } } // namespace v8::internal
An object reference managed by the v8 garbage collector.
Definition: v8.h:198
void AddWeakObjectToCodeDependency(Handle< Object > obj, Handle< DependentCode > dep)
Definition: heap.cc:5341
void EnsureWeakObjectToCodeTable()
Definition: heap.cc:5367
DependentCode * LookupWeakObjectToCodeDependency(Handle< Object > obj)
Definition: heap.cc:5360
static Vector< char > New(int length)
Definition: vector.h:27
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf map
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long mode(MIPS only)") DEFINE_BOOL(enable_always_align_csp
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be NULL
void V8_Fatal(const char *file, int line, const char *format,...)
Definition: logging.cc:75
#define DCHECK(condition)
Definition: logging.h:205
#define arraysize(array)
Definition: macros.h:86
const int KB
Definition: globals.h:106
static void AddWeakObjectToCodeDependency(Isolate *isolate, Handle< Object > object, Handle< Code > code)
void MemCopy(void *dest, const void *src, size_t size)
Definition: utils.h:350
Debugger support for the V8 JavaScript engine.
Definition: accessors.cc:20