Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(223)

Unified Diff: src/hydrogen-load-elimination.cc

Issue 24205004: Rollback trunk to 3.21.16.2 (Closed) Base URL: https://v8.googlecode.com/svn/trunk
Patch Set: Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/hydrogen-load-elimination.h ('k') | src/i18n.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/hydrogen-load-elimination.cc
diff --git a/src/hydrogen-load-elimination.cc b/src/hydrogen-load-elimination.cc
deleted file mode 100644
index 6d01ae573be81d1dd2e86444cfa88af0a9091762..0000000000000000000000000000000000000000
--- a/src/hydrogen-load-elimination.cc
+++ /dev/null
@@ -1,327 +0,0 @@
-// Copyright 2013 the V8 project authors. All rights reserved.
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following
-// disclaimer in the documentation and/or other materials provided
-// with the distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived
-// from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "hydrogen-alias-analysis.h"
-#include "hydrogen-load-elimination.h"
-#include "hydrogen-instructions.h"
-
-namespace v8 {
-namespace internal {
-
-static const int kMaxTrackedFields = 16;
-static const int kMaxTrackedObjects = 5;
-
-// An element in the field approximation list.
-class HFieldApproximation : public ZoneObject {
- public: // Just a data blob.
- HValue* object_;
- HLoadNamedField* last_load_;
- HValue* last_value_;
- HFieldApproximation* next_;
-};
-
-
-// The main datastructure used during load/store elimination. Each in-object
-// field is tracked separately. For each field, store a list of known field
-// values for known objects.
-class HLoadEliminationTable BASE_EMBEDDED {
- public:
- HLoadEliminationTable(Zone* zone, HAliasAnalyzer* aliasing)
- : zone_(zone), fields_(kMaxTrackedFields, zone), aliasing_(aliasing) { }
-
- // Process a load instruction, updating internal table state. If a previous
- // load or store for this object and field exists, return the new value with
- // which the load should be replaced. Otherwise, return {instr}.
- HValue* load(HLoadNamedField* instr) {
- int field = FieldOf(instr->access());
- if (field < 0) return instr;
-
- HValue* object = instr->object()->ActualValue();
- HFieldApproximation* approx = FindOrCreate(object, field);
-
- if (approx->last_value_ == NULL) {
- // Load is not redundant. Fill out a new entry.
- approx->last_load_ = instr;
- approx->last_value_ = instr;
- return instr;
- } else {
- // Eliminate the load. Reuse previously stored value or load instruction.
- return approx->last_value_;
- }
- }
-
- // Process a store instruction, updating internal table state. If a previous
- // store to the same object and field makes this store redundant (e.g. because
- // the stored values are the same), return NULL indicating that this store
- // instruction is redundant. Otherwise, return {instr}.
- HValue* store(HStoreNamedField* instr) {
- int field = FieldOf(instr->access());
- if (field < 0) return instr;
-
- HValue* object = instr->object()->ActualValue();
- HValue* value = instr->value();
-
- // Kill non-equivalent may-alias entries.
- KillFieldInternal(object, field, value);
- if (instr->has_transition()) {
- // A transition store alters the map of the object.
- // TODO(titzer): remember the new map (a constant) for the object.
- KillFieldInternal(object, FieldOf(JSObject::kMapOffset), NULL);
- }
- HFieldApproximation* approx = FindOrCreate(object, field);
-
- if (Equal(approx->last_value_, value)) {
- // The store is redundant because the field already has this value.
- return NULL;
- } else {
- // The store is not redundant. Update the entry.
- approx->last_load_ = NULL;
- approx->last_value_ = value;
- return instr;
- }
- }
-
- // Kill everything in this table.
- void Kill() {
- fields_.Rewind(0);
- }
-
- // Kill all entries matching the given offset.
- void KillOffset(int offset) {
- int field = FieldOf(offset);
- if (field >= 0 && field < fields_.length()) {
- fields_[field] = NULL;
- }
- }
-
- // Compute the field index for the given object access; -1 if not tracked.
- int FieldOf(HObjectAccess access) {
- // Only track kMaxTrackedFields in-object fields.
- if (!access.IsInobject()) return -1;
- return FieldOf(access.offset());
- }
-
- // Print this table to stdout.
- void Print() {
- for (int i = 0; i < fields_.length(); i++) {
- PrintF(" field %d: ", i);
- for (HFieldApproximation* a = fields_[i]; a != NULL; a = a->next_) {
- PrintF("[o%d =", a->object_->id());
- if (a->last_load_ != NULL) PrintF(" L%d", a->last_load_->id());
- if (a->last_value_ != NULL) PrintF(" v%d", a->last_value_->id());
- PrintF("] ");
- }
- PrintF("\n");
- }
- }
-
- private:
- // Find or create an entry for the given object and field pair.
- HFieldApproximation* FindOrCreate(HValue* object, int field) {
- EnsureFields(field + 1);
-
- // Search for a field approximation for this object.
- HFieldApproximation* approx = fields_[field];
- int count = 0;
- while (approx != NULL) {
- if (aliasing_->MustAlias(object, approx->object_)) return approx;
- count++;
- approx = approx->next_;
- }
-
- if (count >= kMaxTrackedObjects) {
- // Pull the last entry off the end and repurpose it for this object.
- approx = ReuseLastApproximation(field);
- } else {
- // Allocate a new entry.
- approx = new(zone_) HFieldApproximation();
- }
-
- // Insert the entry at the head of the list.
- approx->object_ = object;
- approx->last_load_ = NULL;
- approx->last_value_ = NULL;
- approx->next_ = fields_[field];
- fields_[field] = approx;
-
- return approx;
- }
-
- // Kill all entries for a given field that _may_ alias the given object
- // and do _not_ have the given value.
- void KillFieldInternal(HValue* object, int field, HValue* value) {
- if (field >= fields_.length()) return; // Nothing to do.
-
- HFieldApproximation* approx = fields_[field];
- HFieldApproximation* prev = NULL;
- while (approx != NULL) {
- if (aliasing_->MayAlias(object, approx->object_)) {
- if (!Equal(approx->last_value_, value)) {
- // Kill an aliasing entry that doesn't agree on the value.
- if (prev != NULL) {
- prev->next_ = approx->next_;
- } else {
- fields_[field] = approx->next_;
- }
- approx = approx->next_;
- continue;
- }
- }
- prev = approx;
- approx = approx->next_;
- }
- }
-
- bool Equal(HValue* a, HValue* b) {
- if (a == b) return true;
- if (a != NULL && b != NULL) return a->Equals(b);
- return false;
- }
-
- // Remove the last approximation for a field so that it can be reused.
- // We reuse the last entry because it was the first inserted and is thus
- // farthest away from the current instruction.
- HFieldApproximation* ReuseLastApproximation(int field) {
- HFieldApproximation* approx = fields_[field];
- ASSERT(approx != NULL);
-
- HFieldApproximation* prev = NULL;
- while (approx->next_ != NULL) {
- prev = approx;
- approx = approx->next_;
- }
- if (prev != NULL) prev->next_ = NULL;
- return approx;
- }
-
- // Ensure internal storage for the given number of fields.
- void EnsureFields(int num_fields) {
- while (fields_.length() < num_fields) fields_.Add(NULL, zone_);
- }
-
- // Compute the field index for the given in-object offset.
- int FieldOf(int offset) {
- if (offset >= kMaxTrackedFields * kPointerSize) return -1;
- ASSERT((offset % kPointerSize) == 0); // Assume aligned accesses.
- return offset / kPointerSize;
- }
-
- Zone* zone_;
- ZoneList<HFieldApproximation*> fields_;
- HAliasAnalyzer* aliasing_;
-};
-
-
-void HLoadEliminationPhase::Run() {
- for (int i = 0; i < graph()->blocks()->length(); i++) {
- HBasicBlock* block = graph()->blocks()->at(i);
- EliminateLoads(block);
- }
-}
-
-
-// For code de-uglification.
-#define TRACE(x) if (FLAG_trace_load_elimination) PrintF x
-
-
-// Eliminate loads and stores local to a block.
-void HLoadEliminationPhase::EliminateLoads(HBasicBlock* block) {
- HAliasAnalyzer aliasing;
- HLoadEliminationTable table(zone(), &aliasing);
-
- TRACE(("-- load-elim B%d -------------------------------------------------\n",
- block->block_id()));
-
- for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
- bool changed = false;
- HInstruction* instr = it.Current();
-
- switch (instr->opcode()) {
- case HValue::kLoadNamedField: {
- HLoadNamedField* load = HLoadNamedField::cast(instr);
- TRACE((" process L%d field %d (o%d)\n",
- instr->id(),
- table.FieldOf(load->access()),
- load->object()->ActualValue()->id()));
- HValue* result = table.load(load);
- if (result != instr) {
- // The load can be replaced with a previous load or a value.
- TRACE((" replace L%d -> v%d\n", instr->id(), result->id()));
- instr->DeleteAndReplaceWith(result);
- }
- changed = true;
- break;
- }
- case HValue::kStoreNamedField: {
- HStoreNamedField* store = HStoreNamedField::cast(instr);
- TRACE((" process S%d field %d (o%d) = v%d\n",
- instr->id(),
- table.FieldOf(store->access()),
- store->object()->ActualValue()->id(),
- store->value()->id()));
- HValue* result = table.store(store);
- if (result == NULL) {
- // The store is redundant. Remove it.
- TRACE((" remove S%d\n", instr->id()));
- instr->DeleteAndReplaceWith(NULL);
- }
- changed = true;
- break;
- }
- default: {
- if (instr->CheckGVNFlag(kChangesInobjectFields)) {
- TRACE((" kill-all i%d\n", instr->id()));
- table.Kill();
- continue;
- }
- if (instr->CheckGVNFlag(kChangesMaps)) {
- TRACE((" kill-maps i%d\n", instr->id()));
- table.KillOffset(JSObject::kMapOffset);
- }
- if (instr->CheckGVNFlag(kChangesElementsKind)) {
- TRACE((" kill-elements-kind i%d\n", instr->id()));
- table.KillOffset(JSObject::kMapOffset);
- table.KillOffset(JSObject::kElementsOffset);
- }
- if (instr->CheckGVNFlag(kChangesElementsPointer)) {
- TRACE((" kill-elements i%d\n", instr->id()));
- table.KillOffset(JSObject::kElementsOffset);
- }
- }
- // Improvements possible:
- // - learn from HCheckMaps for field 0
- // - remove unobservable stores (write-after-write)
- }
-
- if (changed && FLAG_trace_load_elimination) {
- table.Print();
- }
- }
-}
-
-
-} } // namespace v8::internal
« no previous file with comments | « src/hydrogen-load-elimination.h ('k') | src/i18n.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698