Consider out-of-bounds accesses as escaping uses.

R=titzer@chromium.org
TEST=mjsunit/compiler/escape-analysis

Review URL: https://codereview.chromium.org/23892007

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@16589 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 66c8b527
......@@ -31,7 +31,7 @@ namespace v8 {
namespace internal {
bool HEscapeAnalysisPhase::HasNoEscapingUses(HValue* value) {
bool HEscapeAnalysisPhase::HasNoEscapingUses(HValue* value, int size) {
for (HUseIterator it(value->uses()); !it.Done(); it.Advance()) {
HValue* use = it.value();
if (use->HasEscapingOperandAt(it.index())) {
......@@ -41,7 +41,15 @@ bool HEscapeAnalysisPhase::HasNoEscapingUses(HValue* value) {
}
return false;
}
if (use->RedefinedOperandIndex() == it.index() && !HasNoEscapingUses(use)) {
if (use->HasOutOfBoundsAccess(size)) {
if (FLAG_trace_escape_analysis) {
PrintF("#%d (%s) out of bounds at #%d (%s) @%d\n", value->id(),
value->Mnemonic(), use->id(), use->Mnemonic(), it.index());
}
return false;
}
int redefined_index = use->RedefinedOperandIndex();
if (redefined_index == it.index() && !HasNoEscapingUses(use, size)) {
if (FLAG_trace_escape_analysis) {
PrintF("#%d (%s) escapes redefinition #%d (%s) @%d\n", value->id(),
value->Mnemonic(), use->id(), use->Mnemonic(), it.index());
......@@ -59,7 +67,11 @@ void HEscapeAnalysisPhase::CollectCapturedValues() {
HBasicBlock* block = graph()->blocks()->at(i);
for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
HInstruction* instr = it.Current();
if (instr->IsAllocate() && HasNoEscapingUses(instr)) {
if (!instr->IsAllocate()) continue;
HAllocate* allocate = HAllocate::cast(instr);
if (!allocate->size()->IsInteger32Constant()) continue;
int size_in_bytes = allocate->size()->GetInteger32Constant();
if (HasNoEscapingUses(instr, size_in_bytes)) {
if (FLAG_trace_escape_analysis) {
PrintF("#%d (%s) is being captured\n", instr->id(),
instr->Mnemonic());
......@@ -290,7 +302,6 @@ void HEscapeAnalysisPhase::PerformScalarReplacement() {
HAllocate* allocate = HAllocate::cast(captured_.at(i));
// Compute number of scalar values and start with clean slate.
if (!allocate->size()->IsInteger32Constant()) continue;
int size_in_bytes = allocate->size()->GetInteger32Constant();
number_of_values_ = size_in_bytes / kPointerSize;
number_of_objects_++;
......
......@@ -49,7 +49,7 @@ class HEscapeAnalysisPhase : public HPhase {
private:
void CollectCapturedValues();
bool HasNoEscapingUses(HValue* value);
bool HasNoEscapingUses(HValue* value, int size);
void PerformScalarReplacement();
void AnalyzeDataFlow(HInstruction* instr);
......
......@@ -867,6 +867,7 @@ class HValue : public ZoneObject {
// Escape analysis helpers.
virtual bool HasEscapingOperandAt(int index) { return true; }
virtual bool HasOutOfBoundsAccess(int size) { return false; }
// Representation helpers.
virtual Representation observed_input_representation(int index) {
......@@ -5755,6 +5756,9 @@ class HLoadNamedField V8_FINAL : public HTemplateInstruction<1> {
}
virtual bool HasEscapingOperandAt(int index) V8_OVERRIDE { return false; }
virtual bool HasOutOfBoundsAccess(int size) V8_OVERRIDE {
return !access().IsInobject() || access().offset() >= size;
}
virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
if (index == 0 && access().IsExternalMemory()) {
// object must be external in case of external memory access
......@@ -6070,6 +6074,9 @@ class HStoreNamedField V8_FINAL : public HTemplateInstruction<3> {
virtual bool HasEscapingOperandAt(int index) V8_OVERRIDE {
return index == 1;
}
virtual bool HasOutOfBoundsAccess(int size) V8_OVERRIDE {
return !access().IsInobject() || access().offset() >= size;
}
virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
if (index == 0 && access().IsExternalMemory()) {
// object must be external in case of external memory access
......
......@@ -25,7 +25,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --allow-natives-syntax --use-escape-analysis
// Flags: --allow-natives-syntax --use-escape-analysis --expose-gc
// Test stores on a join path.
......@@ -241,3 +241,33 @@
test(osr2);
test(osr3);
})();
// Test out-of-bounds access on captured objects.
(function testOOB() {
function cons1() {
this.x = 1;
this.y = 2;
this.z = 3;
}
function cons2() {
this.a = 7;
}
function oob(constructor, branch) {
var o = new constructor();
if (branch) {
return o.a;
} else {
return o.z;
}
}
assertEquals(3, oob(cons1, false));
assertEquals(3, oob(cons1, false));
assertEquals(7, oob(cons2, true));
assertEquals(7, oob(cons2, true));
gc(); // Clears type feedback of constructor call.
assertEquals(7, oob(cons2, true));
assertEquals(7, oob(cons2, true));
%OptimizeFunctionOnNextCall(oob);
assertEquals(7, oob(cons2, true));
})();
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment