Revision: 15201
Author: [email protected]
Date: Wed Jun 19 02:25:24 2013
Log: Use type feedback for Array (non-constructor) call sites.
BUG=
[email protected]
Review URL: https://codereview.chromium.org/17155010
http://code.google.com/p/v8/source/detail?r=15201
Added:
/branches/bleeding_edge/test/mjsunit/array-feedback.js
Modified:
/branches/bleeding_edge/src/arm/stub-cache-arm.cc
/branches/bleeding_edge/src/bootstrapper.cc
/branches/bleeding_edge/src/hydrogen.cc
/branches/bleeding_edge/src/ia32/stub-cache-ia32.cc
/branches/bleeding_edge/src/objects.h
/branches/bleeding_edge/src/stub-cache.cc
/branches/bleeding_edge/src/stub-cache.h
/branches/bleeding_edge/src/x64/stub-cache-x64.cc
=======================================
--- /dev/null
+++ /branches/bleeding_edge/test/mjsunit/array-feedback.js Wed Jun 19
02:25:24 2013
@@ -0,0 +1,220 @@
+// 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);
+ })();
+}
=======================================
--- /branches/bleeding_edge/src/arm/stub-cache-arm.cc Mon Jun 17 06:50:56
2013
+++ /branches/bleeding_edge/src/arm/stub-cache-arm.cc Wed Jun 19 02:25:24
2013
@@ -1696,6 +1696,54 @@
// Return the generated code.
return GetCode(Code::FIELD, name);
}
+
+
+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(
@@ -1703,7 +1751,8 @@
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 @@
GenerateMissBranch();
// Return the generated code.
- return GetCode(function);
+ return GetCode(type, name);
}
@@ -1956,7 +2005,8 @@
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 @@
GenerateMissBranch();
// Return the generated code.
- return GetCode(function);
+ return GetCode(type, name);
}
@@ -2038,7 +2088,8 @@
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 @@
GenerateMissBranch();
// Return the generated code.
- return GetCode(function);
+ return GetCode(type, name);
}
@@ -2120,7 +2171,8 @@
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 @@
GenerateMissBranch();
// Return the generated code.
- return GetCode(function);
+ return GetCode(type, name);
}
@@ -2203,7 +2255,8 @@
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 @@
GenerateMissBranch();
// Return the generated code.
- return cell.is_null() ? GetCode(function) : GetCode(Code::NORMAL, name);
+ return GetCode(type, name);
}
@@ -2275,7 +2328,8 @@
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 @@
GenerateMissBranch();
// Return the generated code.
- return cell.is_null() ? GetCode(function) : GetCode(Code::NORMAL, name);
+ return GetCode(type, name);
}
@@ -2383,7 +2437,8 @@
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 @@
GenerateMissBranch();
// Return the generated code.
- return cell.is_null() ? GetCode(function) : GetCode(Code::NORMAL, name);
+ return GetCode(type, name);
}
@@ -2653,7 +2708,8 @@
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 @@
// -----------------------------------
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;
}
=======================================
--- /branches/bleeding_edge/src/bootstrapper.cc Tue Jun 18 00:51:50 2013
+++ /branches/bleeding_edge/src/bootstrapper.cc Wed Jun 19 02:25:24 2013
@@ -859,6 +859,7 @@
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.
=======================================
--- /branches/bleeding_edge/src/hydrogen.cc Wed Jun 19 00:48:41 2013
+++ /branches/bleeding_edge/src/hydrogen.cc Wed Jun 19 02:25:24 2013
@@ -8748,8 +8748,16 @@
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);
=======================================
--- /branches/bleeding_edge/src/ia32/stub-cache-ia32.cc Mon Jun 17 06:50:56
2013
+++ /branches/bleeding_edge/src/ia32/stub-cache-ia32.cc Wed Jun 19 02:25:24
2013
@@ -1694,6 +1694,52 @@
// Return the generated code.
return GetCode(Code::FIELD, name);
}
+
+
+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(
@@ -1701,7 +1747,8 @@
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 @@
GenerateMissBranch();
// Return the generated code.
- return GetCode(function);
+ return GetCode(type, name);
}
@@ -1959,7 +2006,8 @@
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 @@
GenerateMissBranch();
// Return the generated code.
- return GetCode(function);
+ return GetCode(type, name);
}
@@ -2041,7 +2089,8 @@
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 @@
GenerateMissBranch();
// Return the generated code.
- return GetCode(function);
+ return GetCode(type, name);
}
@@ -2125,7 +2174,8 @@
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 @@
GenerateMissBranch();
// Return the generated code.
- return GetCode(function);
+ return GetCode(type, name);
}
@@ -2211,7 +2261,8 @@
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 @@
GenerateMissBranch();
// Return the generated code.
- return cell.is_null() ? GetCode(function) : GetCode(Code::NORMAL, name);
+ return GetCode(type, name);
}
@@ -2287,7 +2338,8 @@
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 @@
GenerateMissBranch();
// Return the generated code.
- return cell.is_null() ? GetCode(function) : GetCode(Code::NORMAL, name);
+ return GetCode(type, name);
}
@@ -2418,7 +2470,8 @@
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 @@
GenerateMissBranch();
// Return the generated code.
- return cell.is_null() ? GetCode(function) : GetCode(Code::NORMAL, name);
+ return GetCode(type, name);
}
@@ -2706,7 +2759,8 @@
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 @@
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;
}
=======================================
--- /branches/bleeding_edge/src/objects.h Fri Jun 14 09:06:12 2013
+++ /branches/bleeding_edge/src/objects.h Wed Jun 19 02:25:24 2013
@@ -5860,8 +5860,8 @@
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)
=======================================
--- /branches/bleeding_edge/src/stub-cache.cc Fri Jun 14 09:06:12 2013
+++ /branches/bleeding_edge/src/stub-cache.cc Wed Jun 19 02:25:24 2013
@@ -644,7 +644,10 @@
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 @@
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;
}
@@ -1972,6 +1977,18 @@
CallOptimization optimization(function);
return optimization.is_simple_api_call();
}
+
+
+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(
@@ -1979,7 +1996,8 @@
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 @@
holder, \
cell, \
function, \
- fname); \
+ fname, \
+ type); \
}
CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE)
#undef CALL_GENERATOR_CASE
=======================================
--- /branches/bleeding_edge/src/stub-cache.h Fri Jun 14 09:06:12 2013
+++ /branches/bleeding_edge/src/stub-cache.h Wed Jun 19 02:25:24 2013
@@ -969,7 +969,12 @@
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 @@
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 @@
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
=======================================
--- /branches/bleeding_edge/src/x64/stub-cache-x64.cc Mon Jun 17 06:50:56
2013
+++ /branches/bleeding_edge/src/x64/stub-cache-x64.cc Wed Jun 19 02:25:24
2013
@@ -1610,6 +1610,52 @@
// Return the generated code.
return GetCode(Code::FIELD, name);
}
+
+
+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(
@@ -1617,7 +1663,8 @@
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 @@
GenerateMissBranch();
// Return the generated code.
- return GetCode(function);
+ return GetCode(type, name);
}
@@ -1867,7 +1914,8 @@
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 @@
GenerateMissBranch();
// Return the generated code.
- return GetCode(function);
+ return GetCode(type, name);
}
@@ -1948,7 +1996,8 @@
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 @@
GenerateMissBranch();
// Return the generated code.
- return GetCode(function);
+ return GetCode(type, name);
}
@@ -2028,7 +2077,8 @@
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 @@
GenerateMissBranch();
// Return the generated code.
- return GetCode(function);
+ return GetCode(type, name);
}
@@ -2108,7 +2158,8 @@
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 @@
GenerateMissBranch();
// Return the generated code.
- return cell.is_null() ? GetCode(function) : GetCode(Code::NORMAL, name);
+ return GetCode(type, name);
}
@@ -2179,7 +2230,8 @@
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<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 @@
GenerateMissBranch();
// Return the generated code.
- return cell.is_null() ? GetCode(function) : GetCode(Code::NORMAL, name);
+ return GetCode(type, name);
}
@@ -2477,7 +2530,8 @@
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 @@
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;
}
--
--
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.