12 for (HUseIterator it(value->
uses()); !it.Done(); it.Advance()) {
14 if (
use->HasEscapingOperandAt(it.index())) {
15 if (FLAG_trace_escape_analysis) {
16 PrintF(
"#%d (%s) escapes through #%d (%s) @%d\n", value->
id(),
21 if (
use->HasOutOfBoundsAccess(
size)) {
22 if (FLAG_trace_escape_analysis) {
23 PrintF(
"#%d (%s) out of bounds at #%d (%s) @%d\n", value->
id(),
28 int redefined_index =
use->RedefinedOperandIndex();
30 if (FLAG_trace_escape_analysis) {
31 PrintF(
"#%d (%s) escapes redefinition #%d (%s) @%d\n", value->
id(),
42 int block_count =
graph()->blocks()->length();
43 for (
int i = 0;
i < block_count; ++
i) {
44 HBasicBlock* block =
graph()->blocks()->at(
i);
45 for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
47 if (!instr->IsAllocate())
continue;
48 HAllocate* allocate = HAllocate::cast(instr);
49 if (!allocate->size()->IsInteger32Constant())
continue;
50 int size_in_bytes = allocate->size()->GetInteger32Constant();
52 if (FLAG_trace_escape_analysis) {
53 PrintF(
"#%d (%s) is being captured\n", instr->
id(),
65 HCapturedObject* state =
67 state->InsertAfter(previous);
75 HConstant* undefined =
graph()->GetConstantUndefined();
76 HCapturedObject* state =
NewState(previous);
78 state->SetOperandAt(index, undefined);
87 HCapturedObject* old_state) {
88 HBasicBlock* block = previous->
block();
89 HCapturedObject* state =
NewState(previous);
93 state->SetOperandAt(index, phi);
102 HCapturedObject* old_state) {
103 HCapturedObject* state =
NewState(previous);
118 HPhi* phi =
new(zone) HPhi(HPhi::kInvalidMergedIndex, zone);
119 for (
int i = 0;
i < block->predecessors()->length();
i++) {
120 phi->AddInput(incoming_value);
129 HCheckMaps* mapcheck) {
131 HValue* value = state->map_value();
134 HCheckValue* check = HCheckValue::New(
135 zone,
NULL, value, mapcheck->maps()->at(0),
false);
136 check->InsertBefore(mapcheck);
144 HLoadNamedField* load,
HValue* load_value) {
145 HValue* replacement = load_value;
150 HForceRepresentation::New(zone,
NULL, load_value, representation);
152 replacement = new_instr;
163 HBasicBlock* allocate_block = allocate->
block();
168 int start = allocate_block->block_id();
169 for (
int i = start;
i <
graph()->blocks()->length();
i++) {
170 HBasicBlock* block =
graph()->blocks()->at(
i);
171 HCapturedObject* state =
StateAt(block);
174 if (!allocate_block->Dominates(block) && allocate_block != block)
continue;
175 if (FLAG_trace_escape_analysis) {
176 PrintF(
"Analyzing data-flow in B%d\n", block->block_id());
180 for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
182 switch (instr->
opcode()) {
183 case HValue::kAllocate: {
184 if (instr != allocate)
continue;
188 case HValue::kLoadNamedField: {
189 HLoadNamedField* load = HLoadNamedField::cast(instr);
191 if (load->object() != allocate)
continue;
192 DCHECK(load->access().IsInobject());
195 load->DeleteAndReplaceWith(replacement);
196 if (FLAG_trace_escape_analysis) {
197 PrintF(
"Replacing load #%d with #%d (%s)\n", load->id(),
202 case HValue::kStoreNamedField: {
203 HStoreNamedField* store = HStoreNamedField::cast(instr);
205 if (store->object() != allocate)
continue;
206 DCHECK(store->access().IsInobject());
208 state->SetOperandAt(index, store->value());
209 if (store->has_transition()) {
210 state->SetOperandAt(0, store->transition());
212 if (store->HasObservableSideEffects()) {
213 state->ReuseSideEffectsFromStore(store);
215 store->DeleteAndReplaceWith(store->ActualValue());
216 if (FLAG_trace_escape_analysis) {
217 PrintF(
"Replacing store #%d%s\n", instr->
id(),
218 store->has_transition() ?
" (with transition)" :
"");
222 case HValue::kArgumentsObject:
223 case HValue::kCapturedObject:
224 case HValue::kSimulate: {
226 if (instr->
OperandAt(
i) != allocate)
continue;
231 case HValue::kCheckHeapObject: {
232 HCheckHeapObject* check = HCheckHeapObject::cast(instr);
233 if (check->value() != allocate)
continue;
234 check->DeleteAndReplaceWith(check->ActualValue());
237 case HValue::kCheckMaps: {
238 HCheckMaps* mapcheck = HCheckMaps::cast(instr);
239 if (mapcheck->value() != allocate)
continue;
241 mapcheck->DeleteAndReplaceWith(mapcheck->ActualValue());
251 for (
int i = 0;
i < block->end()->SuccessorCount();
i++) {
252 HBasicBlock* succ = block->end()->SuccessorAt(
i);
253 if (!allocate_block->Dominates(succ))
continue;
254 if (succ->predecessors()->length() == 1) {
257 }
else if (
StateAt(succ) ==
NULL && succ->IsLoopHeader()) {
269 HCapturedObject* succ_state =
StateAt(succ);
273 if (succ_operand->
IsPhi() && succ_operand->
block() == succ) {
275 HPhi* phi = HPhi::cast(succ_operand);
276 phi->SetOperandAt(succ->PredecessorIndexOf(block), operand);
277 }
else if (succ_operand != operand) {
280 phi->SetOperandAt(succ->PredecessorIndexOf(block), operand);
281 succ_state->SetOperandAt(index, phi);
296 HAllocate* allocate = HAllocate::cast(
captured_.at(
i));
299 int size_in_bytes = allocate->size()->GetInteger32Constant();
308 DCHECK(allocate->HasNoUses());
309 DCHECK(!allocate->IsLinked());
317 if (
graph()->has_osr())
return;
318 int max_fixpoint_iteration_count = FLAG_escape_analysis_iterations;
319 for (
int i = 0;
i < max_fixpoint_iteration_count;
i++) {
HCapturedObject * NewStateForAllocation(HInstruction *prev)
HValue * NewMapCheckAndInsert(HCapturedObject *state, HCheckMaps *mapcheck)
void AnalyzeDataFlow(HInstruction *instr)
HPhi * NewPhiAndInsert(HBasicBlock *block, HValue *incoming_value, int index)
bool HasNoEscapingUses(HValue *value, int size)
HCapturedObject * NewState(HInstruction *prev)
HValue * NewLoadReplacement(HLoadNamedField *load, HValue *load_value)
void PerformScalarReplacement()
HCapturedObject * NewStateForLoopHeader(HInstruction *prev, HCapturedObject *)
void SetStateAt(HBasicBlock *block, HCapturedObject *state)
ZoneList< HCapturedObject * > block_states_
HCapturedObject * StateAt(HBasicBlock *block)
HCapturedObject * NewStateCopy(HInstruction *prev, HCapturedObject *state)
void CollectCapturedValues()
ZoneList< HInstruction * > captured_
void InsertAfter(HInstruction *previous)
virtual Opcode opcode() const =0
virtual int OperandCount() const =0
HBasicBlock * block() const
const char * Mnemonic() const
void SetOperandAt(int index, HValue *value)
HUseIterator uses() const
virtual HValue * OperandAt(int index) const =0
void DeleteAndReplaceWith(HValue *other)
Vector< T > AddBlock(T value, int count, AllocationPolicy allocator=AllocationPolicy())
bool IsSmiOrInteger32() const
enable harmony numeric enable harmony object literal extensions Optimize object size
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 expose gc extension under the specified name show built in functions in stack traces use random jit cookie to mask large constants minimum length for automatic enable preparsing CPU profiler sampling interval in microseconds trace out of bounds accesses to external arrays default size of stack region v8 is allowed to use(in kBytes)") DEFINE_INT(max_stack_trace_source_length
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
#define DCHECK(condition)
void PrintF(const char *format,...)
Debugger support for the V8 JavaScript engine.