Use type feedback for Array (non-constructor) call sites.

BUG=
R=verwaest@chromium.org

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@15201 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 3f69800a
......@@ -1698,12 +1698,61 @@ Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object,
}
Handle<Code> CallStubCompiler::CompileArrayCodeCall(
Handle<Object> object,
Handle<JSObject> holder,
Handle<Cell> cell,
Handle<JSFunction> function,
Handle<String> name,
Code::StubType type) {
Label miss;
// Check that function is still array
const int argc = arguments().immediate();
GenerateNameCheck(name, &miss);
Register receiver = r1;
if (cell.is_null()) {
__ ldr(receiver, MemOperand(sp, argc * kPointerSize));
// Check that the receiver isn't a smi.
__ JumpIfSmi(receiver, &miss);
// Check that the maps haven't changed.
CheckPrototypes(Handle<JSObject>::cast(object), receiver, holder, r3, r0,
r4, name, &miss);
} else {
ASSERT(cell->value() == *function);
GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
&miss);
GenerateLoadFunctionFromCell(cell, function, &miss);
}
Handle<Smi> kind(Smi::FromInt(GetInitialFastElementsKind()), isolate());
Handle<Cell> kind_feedback_cell =
isolate()->factory()->NewCell(kind);
__ mov(r0, Operand(argc));
__ mov(r2, Operand(kind_feedback_cell));
__ mov(r1, Operand(function));
ArrayConstructorStub stub(isolate());
__ TailCallStub(&stub);
__ bind(&miss);
GenerateMissBranch();
// Return the generated code.
return GetCode(type, name);
}
Handle<Code> CallStubCompiler::CompileArrayPushCall(
Handle<Object> object,
Handle<JSObject> holder,
Handle<Cell> cell,
Handle<JSFunction> function,
Handle<String> name) {
Handle<String> name,
Code::StubType type) {
// ----------- S t a t e -------------
// -- r2 : name
// -- lr : return address
......@@ -1947,7 +1996,7 @@ Handle<Code> CallStubCompiler::CompileArrayPushCall(
GenerateMissBranch();
// Return the generated code.
return GetCode(function);
return GetCode(type, name);
}
......@@ -1956,7 +2005,8 @@ Handle<Code> CallStubCompiler::CompileArrayPopCall(
Handle<JSObject> holder,
Handle<Cell> cell,
Handle<JSFunction> function,
Handle<String> name) {
Handle<String> name,
Code::StubType type) {
// ----------- S t a t e -------------
// -- r2 : name
// -- lr : return address
......@@ -2029,7 +2079,7 @@ Handle<Code> CallStubCompiler::CompileArrayPopCall(
GenerateMissBranch();
// Return the generated code.
return GetCode(function);
return GetCode(type, name);
}
......@@ -2038,7 +2088,8 @@ Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall(
Handle<JSObject> holder,
Handle<Cell> cell,
Handle<JSFunction> function,
Handle<String> name) {
Handle<String> name,
Code::StubType type) {
// ----------- S t a t e -------------
// -- r2 : function name
// -- lr : return address
......@@ -2111,7 +2162,7 @@ Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall(
GenerateMissBranch();
// Return the generated code.
return GetCode(function);
return GetCode(type, name);
}
......@@ -2120,7 +2171,8 @@ Handle<Code> CallStubCompiler::CompileStringCharAtCall(
Handle<JSObject> holder,
Handle<Cell> cell,
Handle<JSFunction> function,
Handle<String> name) {
Handle<String> name,
Code::StubType type) {
// ----------- S t a t e -------------
// -- r2 : function name
// -- lr : return address
......@@ -2194,7 +2246,7 @@ Handle<Code> CallStubCompiler::CompileStringCharAtCall(
GenerateMissBranch();
// Return the generated code.
return GetCode(function);
return GetCode(type, name);
}
......@@ -2203,7 +2255,8 @@ Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall(
Handle<JSObject> holder,
Handle<Cell> cell,
Handle<JSFunction> function,
Handle<String> name) {
Handle<String> name,
Code::StubType type) {
// ----------- S t a t e -------------
// -- r2 : function name
// -- lr : return address
......@@ -2266,7 +2319,7 @@ Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall(
GenerateMissBranch();
// Return the generated code.
return cell.is_null() ? GetCode(function) : GetCode(Code::NORMAL, name);
return GetCode(type, name);
}
......@@ -2275,7 +2328,8 @@ Handle<Code> CallStubCompiler::CompileMathFloorCall(
Handle<JSObject> holder,
Handle<Cell> cell,
Handle<JSFunction> function,
Handle<String> name) {
Handle<String> name,
Code::StubType type) {
// ----------- S t a t e -------------
// -- r2 : function name
// -- lr : return address
......@@ -2374,7 +2428,7 @@ Handle<Code> CallStubCompiler::CompileMathFloorCall(
GenerateMissBranch();
// Return the generated code.
return cell.is_null() ? GetCode(function) : GetCode(Code::NORMAL, name);
return GetCode(type, name);
}
......@@ -2383,7 +2437,8 @@ Handle<Code> CallStubCompiler::CompileMathAbsCall(
Handle<JSObject> holder,
Handle<Cell> cell,
Handle<JSFunction> function,
Handle<String> name) {
Handle<String> name,
Code::StubType type) {
// ----------- S t a t e -------------
// -- r2 : function name
// -- lr : return address
......@@ -2472,7 +2527,7 @@ Handle<Code> CallStubCompiler::CompileMathAbsCall(
GenerateMissBranch();
// Return the generated code.
return cell.is_null() ? GetCode(function) : GetCode(Code::NORMAL, name);
return GetCode(type, name);
}
......@@ -2653,7 +2708,8 @@ Handle<Code> CallStubCompiler::CompileCallConstant(
if (HasCustomCallGenerator(function)) {
Handle<Code> code = CompileCustomCall(object, holder,
Handle<Cell>::null(),
function, Handle<String>::cast(name));
function, Handle<String>::cast(name),
Code::CONSTANT_FUNCTION);
// A null handle means bail out to the regular compiler code below.
if (!code.is_null()) return code;
}
......@@ -2719,7 +2775,8 @@ Handle<Code> CallStubCompiler::CompileCallGlobal(
// -----------------------------------
if (HasCustomCallGenerator(function)) {
Handle<Code> code = CompileCustomCall(
object, holder, cell, function, Handle<String>::cast(name));
object, holder, cell, function, Handle<String>::cast(name),
Code::NORMAL);
// A null handle means bail out to the regular compiler code below.
if (!code.is_null()) return code;
}
......
......@@ -859,6 +859,7 @@ bool Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
isolate->initial_object_prototype(),
Builtins::kArrayCode, true, true);
array_function->shared()->DontAdaptArguments();
array_function->shared()->set_function_data(Smi::FromInt(kArrayCode));
// This seems a bit hackish, but we need to make sure Array.length
// is 1.
......
......@@ -8748,8 +8748,16 @@ void HOptimizedGraphBuilder::VisitCall(Call* expr) {
graph()->MarkRecursive();
}
call = PreProcessCall(new(zone()) HCallKnownGlobal(expr->target(),
if (CallStubCompiler::HasCustomCallGenerator(expr->target())) {
// When the target has a custom call IC generator, use the IC,
// because it is likely to generate better code.
HValue* context = environment()->LookupContext();
call = PreProcessCall(
new(zone()) HCallNamed(context, var->name(), argument_count));
} else {
call = PreProcessCall(new(zone()) HCallKnownGlobal(expr->target(),
argument_count));
}
} else {
HValue* context = environment()->LookupContext();
HGlobalObject* receiver = new(zone()) HGlobalObject(context);
......
......@@ -1696,12 +1696,59 @@ Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object,
}
Handle<Code> CallStubCompiler::CompileArrayCodeCall(
Handle<Object> object,
Handle<JSObject> holder,
Handle<Cell> cell,
Handle<JSFunction> function,
Handle<String> name,
Code::StubType type) {
Label miss;
// Check that function is still array
const int argc = arguments().immediate();
GenerateNameCheck(name, &miss);
if (cell.is_null()) {
// Get the receiver from the stack.
__ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
// Check that the receiver isn't a smi.
__ JumpIfSmi(edx, &miss);
CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi,
name, &miss);
} else {
ASSERT(cell->value() == *function);
GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
&miss);
GenerateLoadFunctionFromCell(cell, function, &miss);
}
Handle<Smi> kind(Smi::FromInt(GetInitialFastElementsKind()), isolate());
Handle<Cell> kind_feedback_cell =
isolate()->factory()->NewCell(kind);
__ mov(eax, Immediate(argc));
__ mov(ebx, kind_feedback_cell);
__ mov(edi, function);
ArrayConstructorStub stub(isolate());
__ TailCallStub(&stub);
__ bind(&miss);
GenerateMissBranch();
// Return the generated code.
return GetCode(type, name);
}
Handle<Code> CallStubCompiler::CompileArrayPushCall(
Handle<Object> object,
Handle<JSObject> holder,
Handle<Cell> cell,
Handle<JSFunction> function,
Handle<String> name) {
Handle<String> name,
Code::StubType type) {
// ----------- S t a t e -------------
// -- ecx : name
// -- esp[0] : return address
......@@ -1950,7 +1997,7 @@ Handle<Code> CallStubCompiler::CompileArrayPushCall(
GenerateMissBranch();
// Return the generated code.
return GetCode(function);
return GetCode(type, name);
}
......@@ -1959,7 +2006,8 @@ Handle<Code> CallStubCompiler::CompileArrayPopCall(
Handle<JSObject> holder,
Handle<Cell> cell,
Handle<JSFunction> function,
Handle<String> name) {
Handle<String> name,
Code::StubType type) {
// ----------- S t a t e -------------
// -- ecx : name
// -- esp[0] : return address
......@@ -2032,7 +2080,7 @@ Handle<Code> CallStubCompiler::CompileArrayPopCall(
GenerateMissBranch();
// Return the generated code.
return GetCode(function);
return GetCode(type, name);
}
......@@ -2041,7 +2089,8 @@ Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall(
Handle<JSObject> holder,
Handle<Cell> cell,
Handle<JSFunction> function,
Handle<String> name) {
Handle<String> name,
Code::StubType type) {
// ----------- S t a t e -------------
// -- ecx : function name
// -- esp[0] : return address
......@@ -2116,7 +2165,7 @@ Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall(
GenerateMissBranch();
// Return the generated code.
return GetCode(function);
return GetCode(type, name);
}
......@@ -2125,7 +2174,8 @@ Handle<Code> CallStubCompiler::CompileStringCharAtCall(
Handle<JSObject> holder,
Handle<Cell> cell,
Handle<JSFunction> function,
Handle<String> name) {
Handle<String> name,
Code::StubType type) {
// ----------- S t a t e -------------
// -- ecx : function name
// -- esp[0] : return address
......@@ -2202,7 +2252,7 @@ Handle<Code> CallStubCompiler::CompileStringCharAtCall(
GenerateMissBranch();
// Return the generated code.
return GetCode(function);
return GetCode(type, name);
}
......@@ -2211,7 +2261,8 @@ Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall(
Handle<JSObject> holder,
Handle<Cell> cell,
Handle<JSFunction> function,
Handle<String> name) {
Handle<String> name,
Code::StubType type) {
// ----------- S t a t e -------------
// -- ecx : function name
// -- esp[0] : return address
......@@ -2278,7 +2329,7 @@ Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall(
GenerateMissBranch();
// Return the generated code.
return cell.is_null() ? GetCode(function) : GetCode(Code::NORMAL, name);
return GetCode(type, name);
}
......@@ -2287,7 +2338,8 @@ Handle<Code> CallStubCompiler::CompileMathFloorCall(
Handle<JSObject> holder,
Handle<Cell> cell,
Handle<JSFunction> function,
Handle<String> name) {
Handle<String> name,
Code::StubType type) {
// ----------- S t a t e -------------
// -- ecx : name
// -- esp[0] : return address
......@@ -2409,7 +2461,7 @@ Handle<Code> CallStubCompiler::CompileMathFloorCall(
GenerateMissBranch();
// Return the generated code.
return cell.is_null() ? GetCode(function) : GetCode(Code::NORMAL, name);
return GetCode(type, name);
}
......@@ -2418,7 +2470,8 @@ Handle<Code> CallStubCompiler::CompileMathAbsCall(
Handle<JSObject> holder,
Handle<Cell> cell,
Handle<JSFunction> function,
Handle<String> name) {
Handle<String> name,
Code::StubType type) {
// ----------- S t a t e -------------
// -- ecx : name
// -- esp[0] : return address
......@@ -2515,7 +2568,7 @@ Handle<Code> CallStubCompiler::CompileMathAbsCall(
GenerateMissBranch();
// Return the generated code.
return cell.is_null() ? GetCode(function) : GetCode(Code::NORMAL, name);
return GetCode(type, name);
}
......@@ -2706,7 +2759,8 @@ Handle<Code> CallStubCompiler::CompileCallConstant(
if (HasCustomCallGenerator(function)) {
Handle<Code> code = CompileCustomCall(object, holder,
Handle<Cell>::null(),
function, Handle<String>::cast(name));
function, Handle<String>::cast(name),
Code::CONSTANT_FUNCTION);
// A null handle means bail out to the regular compiler code below.
if (!code.is_null()) return code;
}
......@@ -2797,7 +2851,8 @@ Handle<Code> CallStubCompiler::CompileCallGlobal(
if (HasCustomCallGenerator(function)) {
Handle<Code> code = CompileCustomCall(
object, holder, cell, function, Handle<String>::cast(name));
object, holder, cell, function, Handle<String>::cast(name),
Code::NORMAL);
// A null handle means bail out to the regular compiler code below.
if (!code.is_null()) return code;
}
......
......@@ -5860,8 +5860,8 @@ class Script: public Struct {
V(Math, min, MathMin) \
V(Math, imul, MathImul)
enum BuiltinFunctionId {
kArrayCode,
#define DECLARE_FUNCTION_ID(ignored1, ignore2, name) \
k##name,
FUNCTIONS_WITH_ID_LIST(DECLARE_FUNCTION_ID)
......
......@@ -644,7 +644,10 @@ Handle<Code> StubCache::ComputeCallConstant(int argc,
PROFILE(isolate_,
CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name));
GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code));
JSObject::UpdateMapCodeCache(stub_holder, name, code);
if (CallStubCompiler::CanBeCached(function)) {
JSObject::UpdateMapCodeCache(stub_holder, name, code);
}
return code;
}
......@@ -753,7 +756,9 @@ Handle<Code> StubCache::ComputeCallGlobal(int argc,
PROFILE(isolate(),
CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name));
GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code));
JSObject::UpdateMapCodeCache(stub_holder, name, code);
if (CallStubCompiler::CanBeCached(function)) {
JSObject::UpdateMapCodeCache(stub_holder, name, code);
}
return code;
}
......@@ -1974,12 +1979,25 @@ bool CallStubCompiler::HasCustomCallGenerator(Handle<JSFunction> function) {
}
bool CallStubCompiler::CanBeCached(Handle<JSFunction> function) {
if (function->shared()->HasBuiltinFunctionId()) {
BuiltinFunctionId id = function->shared()->builtin_function_id();
#define CALL_GENERATOR_CASE(name) if (id == k##name) return false;
SITE_SPECIFIC_CALL_GENERATORS(CALL_GENERATOR_CASE)
#undef CALL_GENERATOR_CASE
}
return true;
}
Handle<Code> CallStubCompiler::CompileCustomCall(
Handle<Object> object,
Handle<JSObject> holder,
Handle<Cell> cell,
Handle<JSFunction> function,
Handle<String> fname) {
Handle<String> fname,
Code::StubType type) {
ASSERT(HasCustomCallGenerator(function));
if (function->shared()->HasBuiltinFunctionId()) {
......@@ -1990,7 +2008,8 @@ Handle<Code> CallStubCompiler::CompileCustomCall(
holder, \
cell, \
function, \
fname); \
fname, \
type); \
}
CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE)
#undef CALL_GENERATOR_CASE
......
......@@ -969,7 +969,12 @@ class KeyedStoreStubCompiler: public BaseStoreStubCompiler {
V(StringCharAt) \
V(StringFromCharCode) \
V(MathFloor) \
V(MathAbs)
V(MathAbs) \
V(ArrayCode)
#define SITE_SPECIFIC_CALL_GENERATORS(V) \
V(ArrayCode)
class CallOptimization;
......@@ -1012,6 +1017,7 @@ class CallStubCompiler: public StubCompiler {
Handle<Name> name);
static bool HasCustomCallGenerator(Handle<JSFunction> function);
static bool CanBeCached(Handle<JSFunction> function);
private:
// Compiles a custom call constant/global IC. For constant calls cell is
......@@ -1021,14 +1027,16 @@ class CallStubCompiler: public StubCompiler {
Handle<JSObject> holder,
Handle<Cell> cell,
Handle<JSFunction> function,
Handle<String> name);
Handle<String> name,
Code::StubType type);
#define DECLARE_CALL_GENERATOR(name) \
Handle<Code> Compile##name##Call(Handle<Object> object, \
Handle<JSObject> holder, \
Handle<Cell> cell, \
Handle<JSFunction> function, \
Handle<String> fname);
Handle<String> fname, \
Code::StubType type);
CUSTOM_CALL_IC_GENERATORS(DECLARE_CALL_GENERATOR)
#undef DECLARE_CALL_GENERATOR
......
......@@ -1612,12 +1612,59 @@ Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object,
}
Handle<Code> CallStubCompiler::CompileArrayCodeCall(
Handle<Object> object,
Handle<JSObject> holder,
Handle<Cell> cell,
Handle<JSFunction> function,
Handle<String> name,
Code::StubType type) {
Label miss;
// Check that function is still array
const int argc = arguments().immediate();
GenerateNameCheck(name, &miss);
if (cell.is_null()) {
// Get the receiver from the stack.
__ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
// Check that the receiver isn't a smi.
__ JumpIfSmi(rdx, &miss);
CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi,
name, &miss);
} else {
ASSERT(cell->value() == *function);
GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
&miss);
GenerateLoadFunctionFromCell(cell, function, &miss);
}
Handle<Smi> kind(Smi::FromInt(GetInitialFastElementsKind()), isolate());
Handle<Cell> kind_feedback_cell =
isolate()->factory()->NewCell(kind);
__ movq(rax, Immediate(argc));
__ Move(rbx, kind_feedback_cell);
__ Move(rdi, function);
ArrayConstructorStub stub(isolate());
__ TailCallStub(&stub);
__ bind(&miss);
GenerateMissBranch();
// Return the generated code.
return GetCode(type, name);
}
Handle<Code> CallStubCompiler::CompileArrayPushCall(
Handle<Object> object,
Handle<JSObject> holder,
Handle<Cell> cell,
Handle<JSFunction> function,
Handle<String> name) {
Handle<String> name,
Code::StubType type) {
// ----------- S t a t e -------------
// -- rcx : name
// -- rsp[0] : return address
......@@ -1858,7 +1905,7 @@ Handle<Code> CallStubCompiler::CompileArrayPushCall(
GenerateMissBranch();
// Return the generated code.
return GetCode(function);
return GetCode(type, name);
}
......@@ -1867,7 +1914,8 @@ Handle<Code> CallStubCompiler::CompileArrayPopCall(
Handle<JSObject> holder,
Handle<Cell> cell,
Handle<JSFunction> function,
Handle<String> name) {
Handle<String> name,
Code::StubType type) {
// ----------- S t a t e -------------
// -- rcx : name
// -- rsp[0] : return address
......@@ -1939,7 +1987,7 @@ Handle<Code> CallStubCompiler::CompileArrayPopCall(
GenerateMissBranch();
// Return the generated code.
return GetCode(function);
return GetCode(type, name);
}
......@@ -1948,7 +1996,8 @@ Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall(
Handle<JSObject> holder,
Handle<Cell> cell,
Handle<JSFunction> function,
Handle<String> name) {
Handle<String> name,
Code::StubType type) {
// ----------- S t a t e -------------
// -- rcx : function name
// -- rsp[0] : return address
......@@ -2019,7 +2068,7 @@ Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall(
GenerateMissBranch();
// Return the generated code.
return GetCode(function);
return GetCode(type, name);
}
......@@ -2028,7 +2077,8 @@ Handle<Code> CallStubCompiler::CompileStringCharAtCall(
Handle<JSObject> holder,
Handle<Cell> cell,
Handle<JSFunction> function,
Handle<String> name) {
Handle<String> name,
Code::StubType type) {
// ----------- S t a t e -------------
// -- rcx : function name
// -- rsp[0] : return address
......@@ -2099,7 +2149,7 @@ Handle<Code> CallStubCompiler::CompileStringCharAtCall(
GenerateMissBranch();
// Return the generated code.
return GetCode(function);
return GetCode(type, name);
}
......@@ -2108,7 +2158,8 @@ Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall(
Handle<JSObject> holder,
Handle<Cell> cell,
Handle<JSFunction> function,
Handle<String> name) {
Handle<String> name,
Code::StubType type) {
// ----------- S t a t e -------------
// -- rcx : function name
// -- rsp[0] : return address
......@@ -2170,7 +2221,7 @@ Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall(
GenerateMissBranch();
// Return the generated code.
return cell.is_null() ? GetCode(function) : GetCode(Code::NORMAL, name);
return GetCode(type, name);
}
......@@ -2179,7 +2230,8 @@ Handle<Code> CallStubCompiler::CompileMathFloorCall(
Handle<JSObject> holder,
Handle<Cell> cell,
Handle<JSFunction> function,
Handle<String> name) {
Handle<String> name,
Code::StubType type) {
// TODO(872): implement this.
return Handle<Code>::null();
}
......@@ -2190,7 +2242,8 @@ Handle<Code> CallStubCompiler::CompileMathAbsCall(
Handle<JSObject> holder,
Handle<Cell> cell,
Handle<JSFunction> function,
Handle<String> name) {
Handle<String> name,
Code::StubType type) {
// ----------- S t a t e -------------
// -- rcx : function name
// -- rsp[0] : return address
......@@ -2286,7 +2339,7 @@ Handle<Code> CallStubCompiler::CompileMathAbsCall(
GenerateMissBranch();
// Return the generated code.
return cell.is_null() ? GetCode(function) : GetCode(Code::NORMAL, name);
return GetCode(type, name);
}
......@@ -2477,7 +2530,8 @@ Handle<Code> CallStubCompiler::CompileCallConstant(
if (HasCustomCallGenerator(function)) {
Handle<Code> code = CompileCustomCall(object, holder,
Handle<PropertyCell>::null(),
function, Handle<String>::cast(name));
function, Handle<String>::cast(name),
Code::CONSTANT_FUNCTION);
// A null handle means bail out to the regular compiler code below.
if (!code.is_null()) return code;
}
......@@ -2571,7 +2625,8 @@ Handle<Code> CallStubCompiler::CompileCallGlobal(
if (HasCustomCallGenerator(function)) {
Handle<Code> code = CompileCustomCall(
object, holder, cell, function, Handle<String>::cast(name));
object, holder, cell, function, Handle<String>::cast(name),
Code::NORMAL);
// A null handle means bail out to the regular compiler code below.
if (!code.is_null()) return code;
}
......
// 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 --smi-only-arrays --expose-gc
// Flags: --track-allocation-sites --noalways-opt
// Test element kind of objects.
// Since --smi-only-arrays affects builtins, its default setting at compile
// time sticks if built with snapshot. If --smi-only-arrays is deactivated
// by default, only a no-snapshot build actually has smi-only arrays enabled
// in this test case. Depending on whether smi-only arrays are actually
// enabled, this test takes the appropriate code path to check smi-only arrays.
// support_smi_only_arrays = %HasFastSmiElements(new Array(1,2,3,4,5,6,7,8));
support_smi_only_arrays = true;
optimize_constructed_arrays = true;
if (support_smi_only_arrays) {
print("Tests include smi-only arrays.");
} else {
print("Tests do NOT include smi-only arrays.");
}
if (optimize_constructed_arrays) {
print("Tests include constructed array optimizations.");
} else {
print("Tests do NOT include constructed array optimizations.");
}
var elements_kind = {
fast_smi_only : 'fast smi only elements',
fast : 'fast elements',
fast_double : 'fast double elements',
dictionary : 'dictionary elements',
external_byte : 'external byte elements',
external_unsigned_byte : 'external unsigned byte elements',
external_short : 'external short elements',
external_unsigned_short : 'external unsigned short elements',
external_int : 'external int elements',
external_unsigned_int : 'external unsigned int elements',
external_float : 'external float elements',
external_double : 'external double elements',
external_pixel : 'external pixel elements'
}
function getKind(obj) {
if (%HasFastSmiElements(obj)) return elements_kind.fast_smi_only;
if (%HasFastObjectElements(obj)) return elements_kind.fast;
if (%HasFastDoubleElements(obj)) return elements_kind.fast_double;
if (%HasDictionaryElements(obj)) return elements_kind.dictionary;
}
function isHoley(obj) {
if (%HasFastHoleyElements(obj)) return true;
return false;
}
function assertKind(expected, obj, name_opt) {
if (!support_smi_only_arrays &&
expected == elements_kind.fast_smi_only) {
expected = elements_kind.fast;
}
assertEquals(expected, getKind(obj), name_opt);
}
if (support_smi_only_arrays && optimize_constructed_arrays) {
// Verify that basic elements kind feedback works for non-constructor
// array calls (as long as the call is made through an IC, and not
// a CallStub).
(function (){
function create0() {
return Array();
}
// Calls through ICs need warm up through uninitialized, then
// premonomorphic first.
create0();
create0();
a = create0();
assertKind(elements_kind.fast_smi_only, a);
a[0] = 3.5;
b = create0();
assertKind(elements_kind.fast_double, b);
function create1(arg) {
return Array(arg);
}
create1(0);
create1(0);
a = create1(0);
assertFalse(isHoley(a));
assertKind(elements_kind.fast_smi_only, a);
a[0] = "hello";
b = create1(10);
assertTrue(isHoley(b));
assertKind(elements_kind.fast, b);
a = create1(100000);
assertKind(elements_kind.dictionary, a);
function create3(arg1, arg2, arg3) {
return Array(arg1, arg2, arg3);
}
create3();
create3();
a = create3(1,2,3);
a[0] = 3.5;
b = create3(1,2,3);
assertKind(elements_kind.fast_double, b);
assertFalse(isHoley(b));
})();
// Verify that keyed calls work
(function (){
function create0(name) {
return this[name]();
}
name = "Array";
create0(name);
create0(name);
a = create0(name);
a[0] = 3.5;
b = create0(name);
assertKind(elements_kind.fast_double, b);
})();
// Verify that the IC can't be spoofed by patching
(function (){
function create0() {
return Array();
}
create0();
create0();
a = create0();
assertKind(elements_kind.fast_smi_only, a);
var oldArray = this.Array;
this.Array = function() { return ["hi"]; };
b = create0();
assertEquals(["hi"], b);
this.Array = oldArray;
})();
// Verify that calls are still made through an IC after crankshaft,
// though the type information is reset.
// TODO(mvstanton): instead, consume the type feedback gathered up
// until crankshaft time.
(function (){
function create0() {
return Array();
}
create0();
create0();
a = create0();
a[0] = 3.5;
%OptimizeFunctionOnNextCall(create0);
create0();
create0();
b = create0();
assertKind(elements_kind.fast_smi_only, b);
b[0] = 3.5;
c = create0();
assertKind(elements_kind.fast_double, c);
assertTrue(2 != %GetOptimizationStatus(create0));
})();
// Verify that cross context calls work
(function (){
var realmA = Realm.current();
var realmB = Realm.create();
assertEquals(0, realmA);
assertEquals(1, realmB);
function instanceof_check(type) {
assertTrue(type() instanceof type);
assertTrue(type(5) instanceof type);
assertTrue(type(1,2,3) instanceof type);
}
var realmBArray = Realm.eval(realmB, "Array");
instanceof_check(Array);
instanceof_check(Array);
instanceof_check(Array);
instanceof_check(realmBArray);
instanceof_check(realmBArray);
instanceof_check(realmBArray);
})();
}
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