Commit 677c043f authored by sgjesse@chromium.org's avatar sgjesse@chromium.org

Handle array construction on native code.

The construction of arrays when using the the Array function either as a constructor or a normal function is now handled fully in generated code in most cases. Only when Array is called with one argument which is either negative or abowe JSObject::kInitialMaxFastElementArray (which is currently 1000) or if the allocated object cannot fit in the room left in new space is the runtime system entered.

Two new native code built-in functions are added one for normal invocation and one for the construct call. The existing C++ builtin is renamed, but kept. When the normal invocation cannot be handled in generated code the C++ builtin is called. When the construct invocation cannot be handled in native code the generic construct stub is called (which will end up in the C++ builtin through a construct trampoline).

One thing that might be changed is preserving esi (constructor function) during the handling of a construct call. We know precisily what function we where calling anyway and can just reload it. This could remove the parameter construct_call to ArrayNativeCode and remove the handling of this from that function.

The X64 and ARM implementations are not part of this changelist.
Review URL: http://codereview.chromium.org/193125

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@2899 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent fb2897bc
......@@ -51,6 +51,22 @@ void Builtins::Generate_Adaptor(MacroAssembler* masm, CFunctionId id) {
}
void Builtins::Generate_ArrayCode(MacroAssembler* masm) {
// Just jump to the generic array code.
Code* code = Builtins::builtin(Builtins::ArrayCodeGeneric);
Handle<Code> array_code(code);
__ Jump(array_code, RelocInfo::CODE_TARGET);
}
void Builtins::Generate_ArrayConstructCode(MacroAssembler* masm) {
// Just jump to the generic construct code.
Code* code = Builtins::builtin(Builtins::JSConstructStubGeneric);
Handle<Code> generic_construct_stub(code);
__ Jump(generic_construct_stub, RelocInfo::CODE_TARGET);
}
void Builtins::Generate_JSConstructCall(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- r0 : number of arguments
......
......@@ -654,6 +654,8 @@ void Genesis::CreateRoots(v8::Handle<v8::ObjectTemplate> global_template,
InstallFunction(global, "Array", JS_ARRAY_TYPE, JSArray::kSize,
Top::initial_object_prototype(), Builtins::ArrayCode,
true);
array_function->shared()->set_construct_stub(
Builtins::builtin(Builtins::ArrayConstructCode));
array_function->shared()->DontAdaptArguments();
// This seems a bit hackish, but we need to make sure Array.length
......
......@@ -135,7 +135,9 @@ BUILTIN(EmptyFunction) {
BUILTIN_END
BUILTIN(ArrayCode) {
BUILTIN(ArrayCodeGeneric) {
Counters::array_function_runtime.Increment();
JSArray* array;
if (CalledAsConstructor()) {
array = JSArray::cast(*receiver);
......@@ -166,7 +168,7 @@ BUILTIN(ArrayCode) {
// Take the argument as the length.
obj = array->Initialize(0);
if (obj->IsFailure()) return obj;
if (args.length() == 2) return array->SetElementsLength(args[1]);
return array->SetElementsLength(args[1]);
}
// Optimize the case where there are no parameters passed.
......
......@@ -37,7 +37,7 @@ namespace internal {
\
V(EmptyFunction) \
\
V(ArrayCode) \
V(ArrayCodeGeneric) \
\
V(ArrayPush) \
V(ArrayPop) \
......@@ -83,8 +83,10 @@ namespace internal {
\
/* Uses KeyedLoadIC_Initialize; must be after in list. */ \
V(FunctionCall, BUILTIN, UNINITIALIZED) \
V(FunctionApply, BUILTIN, UNINITIALIZED)
V(FunctionApply, BUILTIN, UNINITIALIZED) \
\
V(ArrayCode, BUILTIN, UNINITIALIZED) \
V(ArrayConstructCode, BUILTIN, UNINITIALIZED)
#ifdef ENABLE_DEBUGGER_SUPPORT
// Define list of builtins used by the debugger implemented in assembly.
......@@ -217,6 +219,9 @@ class Builtins : public AllStatic {
static void Generate_FunctionCall(MacroAssembler* masm);
static void Generate_FunctionApply(MacroAssembler* masm);
static void Generate_ArrayCode(MacroAssembler* masm);
static void Generate_ArrayConstructCode(MacroAssembler* masm);
};
} } // namespace v8::internal
......
This diff is collapsed.
......@@ -142,6 +142,8 @@ namespace internal {
SC(constructed_objects, V8.ConstructedObjects) \
SC(constructed_objects_runtime, V8.ConstructedObjectsRuntime) \
SC(constructed_objects_stub, V8.ConstructedObjectsStub) \
SC(array_function_runtime, V8.ArrayFunctionRuntime) \
SC(array_function_native, V8.ArrayFunctionNative) \
SC(for_in, V8.ForIn) \
SC(enum_cache_hits, V8.EnumCacheHits) \
SC(enum_cache_misses, V8.EnumCacheMisses) \
......
......@@ -452,6 +452,22 @@ void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
}
void Builtins::Generate_ArrayCode(MacroAssembler* masm) {
// Just jump to the generic array code.
Code* code = Builtins::builtin(Builtins::ArrayCodeGeneric);
Handle<Code> array_code(code);
__ Jump(array_code, RelocInfo::CODE_TARGET);
}
void Builtins::Generate_ArrayConstructCode(MacroAssembler* masm) {
// Just jump to the generic construct code.
Code* code = Builtins::builtin(Builtins::JSConstructStubGeneric);
Handle<Code> generic_construct_stub(code);
__ Jump(generic_construct_stub, RelocInfo::CODE_TARGET);
}
void Builtins::Generate_JSConstructCall(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- rax: number of arguments
......
// Copyright 2008 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.
var loop_count = 5
for (var i = 0; i < loop_count; i++) {
var a = new Array();
var b = Array();
assertEquals(0, a.length);
assertEquals(0, b.length);
for (var k = 0; k < 10; k++) {
assertEquals('undefined', typeof a[k]);
assertEquals('undefined', typeof b[k]);
}
}
for (var i = 0; i < loop_count; i++) {
for (var j = 0; j < 100; j++) {
var a = new Array(j);
var b = Array(j);
assertEquals(j, a.length);
assertEquals(j, b.length);
for (var k = 0; k < j; k++) {
assertEquals('undefined', typeof a[k]);
assertEquals('undefined', typeof b[k]);
}
}
}
for (var i = 0; i < loop_count; i++) {
a = new Array(0, 1);
assertArrayEquals([0, 1], a);
a = new Array(0, 1, 2);
assertArrayEquals([0, 1, 2], a);
a = new Array(0, 1, 2, 3);
assertArrayEquals([0, 1, 2, 3], a);
a = new Array(0, 1, 2, 3, 4);
assertArrayEquals([0, 1, 2, 3, 4], a);
a = new Array(0, 1, 2, 3, 4, 5);
assertArrayEquals([0, 1, 2, 3, 4, 5], a);
a = new Array(0, 1, 2, 3, 4, 5, 6);
assertArrayEquals([0, 1, 2, 3, 4, 5, 6], a);
a = new Array(0, 1, 2, 3, 4, 5, 6, 7);
assertArrayEquals([0, 1, 2, 3, 4, 5, 6, 7], a);
a = new Array(0, 1, 2, 3, 4, 5, 6, 7, 8);
assertArrayEquals([0, 1, 2, 3, 4, 5, 6, 7, 8], a);
a = new Array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
assertArrayEquals([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], a);
}
function innerArrayLiteral(n) {
var a = new Array(n);
for (var i = 0; i < n; i++) {
a[i] = i * 2 + 7;
}
return a.join();
}
function testConstructOfSizeSize(n) {
var str = innerArrayLiteral(n);
var a = eval('[' + str + ']');
var b = eval('new Array(' + str + ')')
var c = eval('Array(' + str + ')')
assertEquals(n, a.length);
assertArrayEquals(a, b);
assertArrayEquals(a, c);
}
for (var i = 0; i < loop_count; i++) {
// JSObject::kInitialMaxFastElementArray is 10000.
for (var j = 1000; j < 12000; j += 1000) {
testConstructOfSizeSize(j);
}
}
for (var i = 0; i < loop_count; i++) {
assertArrayEquals(['xxx'], new Array('xxx'));
assertArrayEquals(['xxx'], Array('xxx'));
assertArrayEquals([true], new Array(true));
assertArrayEquals([false], Array(false));
assertArrayEquals([{a:1}], new Array({a:1}));
assertArrayEquals([{b:2}], Array({b:2}));
}
assertThrows('new Array(3.14)');
assertThrows('Array(2.72)');
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