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)