Reviewers: titzer,
Description:
Consider out-of-bounds accesses as escaping uses.
[email protected]
TEST=mjsunit/compiler/escape-analysis
Please review this at https://codereview.chromium.org/23892007/
SVN Base: https://v8.googlecode.com/svn/branches/bleeding_edge
Affected files (+54, -6 lines):
M src/hydrogen-escape-analysis.h
M src/hydrogen-escape-analysis.cc
M src/hydrogen-instructions.h
M test/mjsunit/compiler/escape-analysis.js
Index: src/hydrogen-escape-analysis.cc
diff --git a/src/hydrogen-escape-analysis.cc
b/src/hydrogen-escape-analysis.cc
index
00cfe278012265804fee661dfe33c971ea0d0c05..997e4f9445f79ab3f7ba079acb54be1f6e25deb8
100644
--- a/src/hydrogen-escape-analysis.cc
+++ b/src/hydrogen-escape-analysis.cc
@@ -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_++;
Index: src/hydrogen-escape-analysis.h
diff --git a/src/hydrogen-escape-analysis.h b/src/hydrogen-escape-analysis.h
index
311a653c972370dfab5261aa7f38fc2489d08e87..3e27cc1b48b62d652a2b922c3278bd55b3f2bcaa
100644
--- a/src/hydrogen-escape-analysis.h
+++ b/src/hydrogen-escape-analysis.h
@@ -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);
Index: src/hydrogen-instructions.h
diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h
index
a6d891586cb51942f59f3cb91194610a7ae6efaf..7ff876837b292e6f6a658dfedb60b893aff88f18
100644
--- a/src/hydrogen-instructions.h
+++ b/src/hydrogen-instructions.h
@@ -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) {
@@ -5756,6 +5757,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
@@ -6071,6 +6075,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
Index: test/mjsunit/compiler/escape-analysis.js
diff --git a/test/mjsunit/compiler/escape-analysis.js
b/test/mjsunit/compiler/escape-analysis.js
index
7452e3bd11916d81494f5879f2ab2e3ad78a9e77..74e638a5381a9de6215e7f6649976419c1fce147
100644
--- a/test/mjsunit/compiler/escape-analysis.js
+++ b/test/mjsunit/compiler/escape-analysis.js
@@ -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));
+})();
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.