37 #define TRACE(x) if (FLAG_trace_load_elimination) PrintF x
39 static const int kMaxTrackedFields = 16;
40 static const int kMaxTrackedObjects = 5;
67 : zone_(zone), fields_(kMaxTrackedFields, zone), aliasing_(aliasing) { }
72 case HValue::kLoadNamedField: {
73 HLoadNamedField* l = HLoadNamedField::cast(instr);
74 TRACE((
" process L%d field %d (o%d)\n",
77 l->object()->ActualValue()->id()));
79 if (result != instr &&
80 result->
type().Equals(instr->
type()) &&
83 TRACE((
" replace L%d -> v%d\n", instr->
id(), result->
id()));
88 case HValue::kStoreNamedField: {
89 HStoreNamedField* s = HStoreNamedField::cast(instr);
90 TRACE((
" process S%d field %d (o%d) = v%d\n",
93 s->object()->ActualValue()->id(),
98 TRACE((
" remove S%d\n", instr->
id()));
103 case HValue::kTransitionElementsKind: {
104 HTransitionElementsKind* t = HTransitionElementsKind::cast(instr);
112 TRACE((
" kill-all i%d\n", instr->
id()));
117 TRACE((
" kill-maps i%d\n", instr->
id()));
121 TRACE((
" kill-elements-kind i%d\n", instr->
id()));
126 TRACE((
" kill-elements i%d\n", instr->
id()));
130 TRACE((
" kill-osr i%d\n", instr->
id()));
147 HBasicBlock* succ_block,
149 HBasicBlock* pred_block,
152 if (succ_state ==
NULL) {
153 return pred_state->Copy(succ_block, pred_block, zone);
155 return succ_state->
Merge(succ_block, pred_state, pred_block, zone);
174 copy->EnsureFields(fields_.length());
175 for (
int i = 0; i < fields_.length(); i++) {
176 copy->fields_[i] = fields_[i]->Copy(zone);
178 if (FLAG_trace_load_elimination) {
179 TRACE((
" copy-to B%d\n", succ->block_id()));
187 HBasicBlock* that_block, Zone* zone) {
188 if (that->fields_.length() < fields_.length()) {
190 fields_.Rewind(that->fields_.length());
192 for (
int i = 0; i < fields_.length(); i++) {
194 HFieldApproximation* approx = fields_[i];
195 HFieldApproximation* prev =
NULL;
196 while (approx !=
NULL) {
198 HFieldApproximation* other = that->Find(approx->object_, i);
199 if (other ==
NULL || !Equal(approx->last_value_, other->last_value_)) {
202 prev->next_ = approx->next_;
204 fields_[i] = approx->next_;
206 approx = approx->next_;
210 approx = approx->next_;
213 if (FLAG_trace_load_elimination) {
214 TRACE((
" merge-to B%d\n", succ->block_id()));
227 HValue* load(HLoadNamedField* instr) {
229 ASSERT(!instr->access().IsInobject() ||
230 instr->access().existing_inobject_property());
232 int field = FieldOf(instr->access());
233 if (field < 0)
return instr;
255 HValue* store(HStoreNamedField* instr) {
256 if (instr->access().IsInobject() &&
257 !instr->access().existing_inobject_property()) {
258 TRACE((
" skipping non existing property initialization store\n"));
262 int field = FieldOf(instr->access());
263 if (field < 0)
return KillIfMisaligned(instr);
265 HValue*
object = instr->object()->ActualValue();
266 HValue* value = instr->value();
268 if (instr->has_transition()) {
275 KillFieldInternal(
object, field, value);
277 HFieldApproximation* approx = FindOrCreate(
object, field);
279 if (Equal(approx->last_value_, value)) {
284 approx->last_value_ = value;
295 void KillOffset(
int offset) {
296 int field = FieldOf(offset);
297 if (field >= 0 && field < fields_.length()) {
298 fields_[field] =
NULL;
303 void KillStore(HStoreNamedField* s) {
304 int field = FieldOf(s->access());
306 KillFieldInternal(s->object()->ActualValue(), field, s->value());
313 HValue* KillIfMisaligned(HStoreNamedField* instr) {
314 HObjectAccess access = instr->access();
315 if (access.IsInobject()) {
316 int offset = access.offset();
319 HValue*
object = instr->object()->ActualValue();
321 KillFieldInternal(
object, field,
NULL);
324 int size = access.representation().size();
325 int next_field = (offset + size - 1) / kPointerSize;
326 if (next_field != field) KillFieldInternal(
object, next_field,
NULL);
333 HFieldApproximation* Find(HValue*
object,
int field) {
335 HFieldApproximation* approx = fields_[field];
336 while (approx !=
NULL) {
337 if (aliasing_->
MustAlias(
object, approx->object_))
return approx;
338 approx = approx->next_;
344 HFieldApproximation* FindOrCreate(HValue*
object,
int field) {
345 EnsureFields(field + 1);
348 HFieldApproximation* approx = fields_[field];
350 while (approx !=
NULL) {
351 if (aliasing_->
MustAlias(
object, approx->object_))
return approx;
353 approx = approx->next_;
356 if (count >= kMaxTrackedObjects) {
358 approx = ReuseLastApproximation(field);
361 approx =
new(zone_) HFieldApproximation();
365 approx->object_ = object;
366 approx->last_value_ =
NULL;
367 approx->next_ = fields_[field];
368 fields_[field] = approx;
375 void KillFieldInternal(HValue*
object,
int field, HValue* value) {
376 if (field >= fields_.length())
return;
378 HFieldApproximation* approx = fields_[field];
379 HFieldApproximation* prev =
NULL;
380 while (approx !=
NULL) {
381 if (aliasing_->
MayAlias(
object, approx->object_)) {
382 if (!Equal(approx->last_value_, value)) {
385 prev->next_ = approx->next_;
387 fields_[field] = approx->next_;
389 approx = approx->next_;
394 approx = approx->next_;
398 bool Equal(HValue* a, HValue* b) {
399 if (a == b)
return true;
409 HFieldApproximation* ReuseLastApproximation(
int field) {
410 HFieldApproximation* approx = fields_[field];
413 HFieldApproximation* prev =
NULL;
414 while (approx->next_ !=
NULL) {
416 approx = approx->next_;
418 if (prev !=
NULL) prev->next_ =
NULL;
423 int FieldOf(HObjectAccess access) {
424 return access.IsInobject() ? FieldOf(access.offset()) : -1;
428 int FieldOf(
int offset) {
429 if (offset >= kMaxTrackedFields * kPointerSize)
return -1;
431 if ((offset % kPointerSize) != 0)
return -1;
436 void EnsureFields(
int num_fields) {
437 if (fields_.length() < num_fields) {
438 fields_.AddBlock(
NULL, num_fields - fields_.length(), zone_);
444 for (
int i = 0; i < fields_.length(); i++) {
446 for (HFieldApproximation* a = fields_[i]; a !=
NULL; a = a->next_) {
447 PrintF(
"[o%d =", a->object_->id());
448 if (a->last_value_ !=
NULL)
PrintF(
" v%d", a->last_value_->id());
456 ZoneList<HFieldApproximation*> fields_;
457 HAliasAnalyzer* aliasing_;
465 : zone_(zone), stores_(5, zone) { }
473 if (instr->IsStoreNamedField()) {
474 stores_.
Add(HStoreNamedField::cast(instr), zone_);
496 for (
int i = 0; i < stores_.length(); i++) {
497 table->KillStore(stores_[i]);
503 flags_.
Add(that->flags_);
504 for (
int i = 0; i < that->stores_.length(); i++) {
505 stores_.
Add(that->stores_[i], zone);
520 engine(
graph(), zone());
530 for (
int i = 0; i <
graph()->blocks()->length(); i++) {
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter NULL
void PrintF(const char *format,...)
bool CheckChangesFlag(GVNFlag f) const
HBasicBlock * block() const
void AnalyzeDominatedBlocks(HBasicBlock *root, State *initial)
HLoadEliminationEffects(Zone *zone)
#define ASSERT(condition)
HLoadEliminationTable * Process(HInstruction *instr, Zone *zone)
Representation representation() const
HFieldApproximation * Copy(Zone *zone)
bool MayAlias(HValue *a, HValue *b)
void Union(HLoadEliminationEffects *that, Zone *zone)
static HLoadEliminationTable * Finish(HLoadEliminationTable *state, HBasicBlock *block, Zone *zone)
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object size
static HLoadEliminationTable * Merge(HLoadEliminationTable *succ_state, HBasicBlock *succ_block, HLoadEliminationTable *pred_state, HBasicBlock *pred_block, Zone *zone)
bool Equals(const Representation &other) const
GVNFlagSet ChangesFlags() const
static const int kElementsOffset
void DeleteAndReplaceWith(HValue *other)
bool MustAlias(HValue *a, HValue *b)
virtual Opcode opcode() const =0
static const int kMapOffset
bool Contains(E element) const
State * AnalyzeOneBlock(HBasicBlock *block, State *state)
HFieldApproximation * next_
void Print(const v8::FunctionCallbackInfo< v8::Value > &args)
void Add(const T &element, AllocationPolicy allocator=AllocationPolicy())
void Apply(HLoadEliminationTable *table)
HLoadEliminationTable(Zone *zone, HAliasAnalyzer *aliasing)
void Process(HInstruction *instr, Zone *zone)