Commit a0bc9eb0 authored by antonm@chromium.org's avatar antonm@chromium.org

Add more bailouts for Array.slice over arguments.

Unfortunately, arguments is pretty much the normal JS object.  For now
I am adding more sanity checks (in hope that typically arguments
list is rather short.)  However it probably requires more systematic
treatment, for example, we could optimistically copy elements until
we meet first hole and in this case resort to JS builtin.

Review URL: http://codereview.chromium.org/6062006

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@6256 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 476cacad
......@@ -636,15 +636,20 @@ BUILTIN(ArraySlice) {
return CallJsBuiltin("ArraySlice", args);
}
elms = FixedArray::cast(JSObject::cast(receiver)->elements());
len = elms->length();
#ifdef DEBUG
// Arguments object by construction should have no holes, check it.
if (FLAG_enable_slow_asserts) {
for (int i = 0; i < len; i++) {
ASSERT(elms->get(i) != Heap::the_hole_value());
Object* len_obj = JSObject::cast(receiver)
->InObjectPropertyAt(Heap::arguments_length_index);
if (!len_obj->IsSmi()) {
return CallJsBuiltin("ArraySlice", args);
}
len = Smi::cast(len_obj)->value();
if (len > elms->length()) {
return CallJsBuiltin("ArraySlice", args);
}
for (int i = 0; i < len; i++) {
if (elms->get(i) == Heap::the_hole_value()) {
return CallJsBuiltin("ArraySlice", args);
}
}
#endif
}
ASSERT(len >= 0);
int n_arguments = args.length() - 1;
......
......@@ -231,3 +231,62 @@
func(['a', 1, undefined], 'a', 1, undefined);
func(['a', 1, undefined, void(0)], 'a', 1, undefined, void(0));
})();
// Check slicing on arguments object when missing arguments get assigined.
(function() {
function func(x, y) {
assertEquals(1, arguments.length);
assertEquals(undefined, y);
y = 239;
assertEquals(1, arguments.length); // arguments length is the same.
assertEquals([x], Array.prototype.slice.call(arguments, 0));
}
func('a');
})();
// Check slicing on arguments object when length property has been set.
(function() {
function func(x, y) {
assertEquals(1, arguments.length);
arguments.length = 7;
assertEquals([x,,,,,,,], Array.prototype.slice.call(arguments, 0));
}
func('a');
})();
// Check slicing on arguments object when length property has been set to
// some strange value.
(function() {
function func(x, y) {
assertEquals(1, arguments.length);
arguments.length = 'foobar';
assertEquals([], Array.prototype.slice.call(arguments, 0));
}
func('a');
})();
// Check slicing on arguments object when extra argument has been added
// via indexed assignment.
(function() {
function func(x, y) {
assertEquals(1, arguments.length);
arguments[3] = 239;
assertEquals([x], Array.prototype.slice.call(arguments, 0));
}
func('a');
})();
// Check slicing on arguments object when argument has been deleted by index.
(function() {
function func(x, y, z) {
assertEquals(3, arguments.length);
delete arguments[1];
assertEquals([x,,z], Array.prototype.slice.call(arguments, 0));
}
func('a', 'b', 'c');
})();
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