Fix fast array literals to ignore prototype chain.

This makes sure that boilerplate objects for array literals with
non-constant elements (which will contain the hole at non-constant
positions) will not cause prototype chain lookups when generating
optimized code.

R=erik.corry@gmail.com
BUG=chromium:123512
TEST=mjsunit/regress/regress-123512

Review URL: https://chromiumcodereview.appspot.com/10105025

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@11350 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 47c4a5b4
...@@ -4659,9 +4659,10 @@ void LCodeGen::EmitDeepCopy(Handle<JSObject> object, ...@@ -4659,9 +4659,10 @@ void LCodeGen::EmitDeepCopy(Handle<JSObject> object,
__ str(r2, FieldMemOperand(result, total_offset + 4)); __ str(r2, FieldMemOperand(result, total_offset + 4));
} }
} else if (elements->IsFixedArray()) { } else if (elements->IsFixedArray()) {
Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements);
for (int i = 0; i < elements_length; i++) { for (int i = 0; i < elements_length; i++) {
int total_offset = elements_offset + FixedArray::OffsetOfElementAt(i); int total_offset = elements_offset + FixedArray::OffsetOfElementAt(i);
Handle<Object> value = JSObject::GetElement(object, i); Handle<Object> value(fast_elements->get(i));
if (value->IsJSObject()) { if (value->IsJSObject()) {
Handle<JSObject> value_object = Handle<JSObject>::cast(value); Handle<JSObject> value_object = Handle<JSObject>::cast(value);
__ add(r2, result, Operand(*offset)); __ add(r2, result, Operand(*offset));
......
...@@ -3749,10 +3749,11 @@ static bool IsFastLiteral(Handle<JSObject> boilerplate, ...@@ -3749,10 +3749,11 @@ static bool IsFastLiteral(Handle<JSObject> boilerplate,
if (boilerplate->HasFastDoubleElements()) { if (boilerplate->HasFastDoubleElements()) {
*total_size += FixedDoubleArray::SizeFor(elements->length()); *total_size += FixedDoubleArray::SizeFor(elements->length());
} else if (boilerplate->HasFastElements()) { } else if (boilerplate->HasFastElements()) {
Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements);
int length = elements->length(); int length = elements->length();
for (int i = 0; i < length; i++) { for (int i = 0; i < length; i++) {
if ((*max_properties)-- == 0) return false; if ((*max_properties)-- == 0) return false;
Handle<Object> value = JSObject::GetElement(boilerplate, i); Handle<Object> value(fast_elements->get(i));
if (value->IsJSObject()) { if (value->IsJSObject()) {
Handle<JSObject> value_object = Handle<JSObject>::cast(value); Handle<JSObject> value_object = Handle<JSObject>::cast(value);
if (!IsFastLiteral(value_object, if (!IsFastLiteral(value_object,
......
...@@ -4514,9 +4514,10 @@ void LCodeGen::EmitDeepCopy(Handle<JSObject> object, ...@@ -4514,9 +4514,10 @@ void LCodeGen::EmitDeepCopy(Handle<JSObject> object,
__ mov(FieldOperand(result, total_offset + 4), Immediate(value_high)); __ mov(FieldOperand(result, total_offset + 4), Immediate(value_high));
} }
} else if (elements->IsFixedArray()) { } else if (elements->IsFixedArray()) {
Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements);
for (int i = 0; i < elements_length; i++) { for (int i = 0; i < elements_length; i++) {
int total_offset = elements_offset + FixedArray::OffsetOfElementAt(i); int total_offset = elements_offset + FixedArray::OffsetOfElementAt(i);
Handle<Object> value = JSObject::GetElement(object, i); Handle<Object> value(fast_elements->get(i));
if (value->IsJSObject()) { if (value->IsJSObject()) {
Handle<JSObject> value_object = Handle<JSObject>::cast(value); Handle<JSObject> value_object = Handle<JSObject>::cast(value);
__ lea(ecx, Operand(result, *offset)); __ lea(ecx, Operand(result, *offset));
......
...@@ -4555,9 +4555,10 @@ void LCodeGen::EmitDeepCopy(Handle<JSObject> object, ...@@ -4555,9 +4555,10 @@ void LCodeGen::EmitDeepCopy(Handle<JSObject> object,
__ sw(a2, FieldMemOperand(result, total_offset + 4)); __ sw(a2, FieldMemOperand(result, total_offset + 4));
} }
} else if (elements->IsFixedArray()) { } else if (elements->IsFixedArray()) {
Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements);
for (int i = 0; i < elements_length; i++) { for (int i = 0; i < elements_length; i++) {
int total_offset = elements_offset + FixedArray::OffsetOfElementAt(i); int total_offset = elements_offset + FixedArray::OffsetOfElementAt(i);
Handle<Object> value = JSObject::GetElement(object, i); Handle<Object> value(fast_elements->get(i));
if (value->IsJSObject()) { if (value->IsJSObject()) {
Handle<JSObject> value_object = Handle<JSObject>::cast(value); Handle<JSObject> value_object = Handle<JSObject>::cast(value);
__ Addu(a2, result, Operand(*offset)); __ Addu(a2, result, Operand(*offset));
......
...@@ -4280,9 +4280,10 @@ void LCodeGen::EmitDeepCopy(Handle<JSObject> object, ...@@ -4280,9 +4280,10 @@ void LCodeGen::EmitDeepCopy(Handle<JSObject> object,
__ movq(FieldOperand(result, total_offset), rcx); __ movq(FieldOperand(result, total_offset), rcx);
} }
} else if (elements->IsFixedArray()) { } else if (elements->IsFixedArray()) {
Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements);
for (int i = 0; i < elements_length; i++) { for (int i = 0; i < elements_length; i++) {
int total_offset = elements_offset + FixedArray::OffsetOfElementAt(i); int total_offset = elements_offset + FixedArray::OffsetOfElementAt(i);
Handle<Object> value = JSObject::GetElement(object, i); Handle<Object> value(fast_elements->get(i));
if (value->IsJSObject()) { if (value->IsJSObject()) {
Handle<JSObject> value_object = Handle<JSObject>::cast(value); Handle<JSObject> value_object = Handle<JSObject>::cast(value);
__ lea(rcx, Operand(result, *offset)); __ lea(rcx, Operand(result, *offset));
......
// Copyright 2012 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.
// Flags: --allow-natives-syntax
// Test that boilerplate objects for array literals with non-constant
// elements (which will contain the hole at non-constant positions) will
// not cause prototype chain lookups when generating optimized code.
function f(x) {
return [x][0];
}
// Test data element on prototype.
Object.prototype[0] = 23;
assertSame(1, f(1));
assertSame(2, f(2));
%OptimizeFunctionOnNextCall(f);
assertSame(3, f(3));
%DeoptimizeFunction(f);
// Test accessor element on prototype.
Object.prototype.__defineGetter__(0, function() { throw Error(); });
assertSame(4, f(4));
assertSame(5, f(5));
%OptimizeFunctionOnNextCall(f);
assertSame(6, f(6));
%DeoptimizeFunction(f);
// Test the same on boilerplate objects for object literals that contain
// both non-constant properties and non-constant elements.
function g(x, y) {
var o = { foo:x, 0:y };
return o.foo + o[0];
}
// Test data property and element on prototype.
Object.prototype[0] = 23;
Object.prototype.foo = 42;
assertSame(3, g(1, 2));
assertSame(5, g(2, 3));
%OptimizeFunctionOnNextCall(g);
assertSame(7, g(3, 4));
%DeoptimizeFunction(g);
// Test accessor property and element on prototype.
Object.prototype.__defineGetter__(0, function() { throw Error(); });
Object.prototype.__defineGetter__('foo', function() { throw Error(); });
assertSame(3, g(1, 2));
assertSame(5, g(2, 3));
%OptimizeFunctionOnNextCall(g);
assertSame(7, g(3, 4));
%DeoptimizeFunction(g);
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