Revision: 4381
Author: [email protected]
Date: Mon Apr 12 00:05:24 2010
Log: Faster invocation of custom comparator function.
Review URL: http://codereview.chromium.org/1623004
http://code.google.com/p/v8/source/detail?r=4381
Modified:
/branches/bleeding_edge/src/arm/codegen-arm.cc
/branches/bleeding_edge/src/arm/codegen-arm.h
/branches/bleeding_edge/src/arm/virtual-frame-arm.cc
/branches/bleeding_edge/src/arm/virtual-frame-arm.h
/branches/bleeding_edge/src/array.js
/branches/bleeding_edge/src/codegen.h
/branches/bleeding_edge/src/ia32/codegen-ia32.cc
/branches/bleeding_edge/src/ia32/codegen-ia32.h
/branches/bleeding_edge/src/ia32/virtual-frame-ia32.cc
/branches/bleeding_edge/src/ia32/virtual-frame-ia32.h
/branches/bleeding_edge/src/runtime.cc
/branches/bleeding_edge/src/runtime.h
/branches/bleeding_edge/src/x64/codegen-x64.cc
/branches/bleeding_edge/src/x64/codegen-x64.h
/branches/bleeding_edge/src/x64/virtual-frame-x64.cc
/branches/bleeding_edge/src/x64/virtual-frame-x64.h
/branches/bleeding_edge/test/mjsunit/fuzz-natives.js
=======================================
--- /branches/bleeding_edge/src/arm/codegen-arm.cc Fri Apr 9 11:25:51 2010
+++ /branches/bleeding_edge/src/arm/codegen-arm.cc Mon Apr 12 00:05:24 2010
@@ -4031,6 +4031,22 @@
frame_->CallStub(&stub, 1);
frame_->EmitPush(r0);
}
+
+
+void CodeGenerator::GenerateCallFunction(ZoneList<Expression*>* args) {
+ Comment cmnt(masm_, "[ GenerateCallFunction");
+
+ ASSERT(args->length() >= 2);
+
+ int n_args = args->length() - 2; // for receiver and function.
+ Load(args->at(0)); // receiver
+ for (int i = 0; i < n_args; i++) {
+ Load(args->at(i + 1));
+ }
+ Load(args->at(n_args + 1)); // function
+ frame_->CallJSFunction(n_args);
+ frame_->EmitPush(r0);
+}
void CodeGenerator::GenerateMathSin(ZoneList<Expression*>* args) {
=======================================
--- /branches/bleeding_edge/src/arm/codegen-arm.h Fri Apr 9 11:25:51 2010
+++ /branches/bleeding_edge/src/arm/codegen-arm.h Mon Apr 12 00:05:24 2010
@@ -410,6 +410,9 @@
// Fast support for number to string.
void GenerateNumberToString(ZoneList<Expression*>* args);
+ // Fast call for custom callbacks.
+ void GenerateCallFunction(ZoneList<Expression*>* args);
+
// Fast call to math functions.
void GenerateMathPow(ZoneList<Expression*>* args);
void GenerateMathSin(ZoneList<Expression*>* args);
=======================================
--- /branches/bleeding_edge/src/arm/virtual-frame-arm.cc Thu Apr 8
15:30:30 2010
+++ /branches/bleeding_edge/src/arm/virtual-frame-arm.cc Mon Apr 12
00:05:24 2010
@@ -253,6 +253,20 @@
Adjust(kHandlerSize - 1);
__ PushTryHandler(IN_JAVASCRIPT, type);
}
+
+
+void VirtualFrame::CallJSFunction(int arg_count) {
+ // InvokeFunction requires function in r1.
+ EmitPop(r1);
+
+ // +1 for receiver.
+ Forget(arg_count + 1);
+ ASSERT(cgen()->HasValidEntryRegisters());
+ ParameterCount count(arg_count);
+ __ InvokeFunction(r1, count, CALL_FUNCTION);
+ // Restore the context.
+ __ ldr(cp, Context());
+}
void VirtualFrame::CallRuntime(Runtime::Function* f, int arg_count) {
=======================================
--- /branches/bleeding_edge/src/arm/virtual-frame-arm.h Thu Apr 8 15:30:30
2010
+++ /branches/bleeding_edge/src/arm/virtual-frame-arm.h Mon Apr 12 00:05:24
2010
@@ -288,6 +288,10 @@
ASSERT(cgen()->HasValidEntryRegisters());
masm()->CallStub(stub);
}
+
+ // Call JS function from top of the stack with arguments
+ // taken from the stack.
+ void CallJSFunction(int arg_count);
// Call runtime given the number of arguments expected on (and
// removed from) the stack.
=======================================
--- /branches/bleeding_edge/src/array.js Wed Apr 7 06:13:06 2010
+++ /branches/bleeding_edge/src/array.js Mon Apr 12 00:05:24 2010
@@ -644,6 +644,8 @@
// In-place QuickSort algorithm.
// For short (length <= 22) arrays, insertion sort is used for
efficiency.
+ var global_receiver;
+
function InsertionSortWithFunc(a, from, to) {
for (var i = from + 1; i < to; i++) {
var element = a[i];
@@ -654,8 +656,7 @@
// The search interval is a[min..max[
while (min < max) {
var mid = min + ((max - min) >> 1);
- var order = (a[mid] === element) ?
- 0 : comparefn.call(null, a[mid], element);
+ var order = %_CallFunction(global_receiver, a[mid], element,
comparefn);
if (order == 0) {
min = max = mid;
break;
@@ -692,8 +693,7 @@
// From i to high_start are elements that haven't been compared yet.
for (var i = from + 1; i < high_start; ) {
var element = a[i];
- var order = (element === pivot) ?
- 0 : comparefn.call(null, element, pivot);
+ var order = %_CallFunction(global_receiver, element, pivot,
comparefn);
if (order < 0) {
a[i] = a[low_end];
a[low_end] = element;
@@ -938,6 +938,7 @@
}
if(IS_FUNCTION(comparefn)) {
+ global_receiver = %GetGlobalReceiver();
QuickSortWithFunc(this, 0, num_non_undefined);
} else {
QuickSort(this, 0, num_non_undefined);
=======================================
--- /branches/bleeding_edge/src/codegen.h Thu Apr 8 15:30:30 2010
+++ /branches/bleeding_edge/src/codegen.h Mon Apr 12 00:05:24 2010
@@ -104,6 +104,7 @@
F(IsNonNegativeSmi, 1,
1) \
F(IsArray, 1,
1) \
F(IsRegExp, 1,
1) \
+ F(CallFunction, -1 /* receiver + n args + function */,
1) \
F(IsConstructCall, 0,
1) \
F(ArgumentsLength, 0,
1) \
F(Arguments, 1,
1) \
=======================================
--- /branches/bleeding_edge/src/ia32/codegen-ia32.cc Thu Apr 8 06:41:11
2010
+++ /branches/bleeding_edge/src/ia32/codegen-ia32.cc Mon Apr 12 00:05:24
2010
@@ -6520,6 +6520,22 @@
Result result = frame_->CallStub(&stub, 1);
frame_->Push(&result);
}
+
+
+void CodeGenerator::GenerateCallFunction(ZoneList<Expression*>* args) {
+ Comment cmnt(masm_, "[ GenerateCallFunction");
+
+ ASSERT(args->length() >= 2);
+
+ int n_args = args->length() - 2; // for receiver and function.
+ Load(args->at(0)); // receiver
+ for (int i = 0; i < n_args; i++) {
+ Load(args->at(i + 1));
+ }
+ Load(args->at(n_args + 1)); // function
+ Result result = frame_->CallJSFunction(n_args);
+ frame_->Push(&result);
+}
// Generates the Math.pow method - only handles special cases and branches
to
=======================================
--- /branches/bleeding_edge/src/ia32/codegen-ia32.h Wed Apr 7 01:18:51 2010
+++ /branches/bleeding_edge/src/ia32/codegen-ia32.h Mon Apr 12 00:05:24 2010
@@ -631,6 +631,9 @@
// Fast support for number to string.
void GenerateNumberToString(ZoneList<Expression*>* args);
+ // Fast call for custom callbacks.
+ void GenerateCallFunction(ZoneList<Expression*>* args);
+
// Fast call to math functions.
void GenerateMathPow(ZoneList<Expression*>* args);
void GenerateMathSin(ZoneList<Expression*>* args);
=======================================
--- /branches/bleeding_edge/src/ia32/virtual-frame-ia32.cc Thu Mar 25
05:44:15 2010
+++ /branches/bleeding_edge/src/ia32/virtual-frame-ia32.cc Mon Apr 12
00:05:24 2010
@@ -907,6 +907,25 @@
arg1->Unuse();
return RawCallStub(stub);
}
+
+
+Result VirtualFrame::CallJSFunction(int arg_count) {
+ Result function = Pop();
+
+ // InvokeFunction requires function in edi. Move it in there.
+ function.ToRegister(edi);
+ function.Unuse();
+
+ // +1 for receiver.
+ PrepareForCall(arg_count + 1, arg_count + 1);
+ ASSERT(cgen()->HasValidEntryRegisters());
+ ParameterCount count(arg_count);
+ __ InvokeFunction(edi, count, CALL_FUNCTION);
+ RestoreContextRegister();
+ Result result = cgen()->allocator()->Allocate(eax);
+ ASSERT(result.is_valid());
+ return result;
+}
Result VirtualFrame::CallRuntime(Runtime::Function* f, int arg_count) {
=======================================
--- /branches/bleeding_edge/src/ia32/virtual-frame-ia32.h Thu Mar 25
06:18:00 2010
+++ /branches/bleeding_edge/src/ia32/virtual-frame-ia32.h Mon Apr 12
00:05:24 2010
@@ -331,6 +331,10 @@
// arguments are consumed by the call.
Result CallStub(CodeStub* stub, Result* arg0, Result* arg1);
+ // Call JS function from top of the stack with arguments
+ // taken from the stack.
+ Result CallJSFunction(int arg_count);
+
// Call runtime given the number of arguments expected on (and
// removed from) the stack.
Result CallRuntime(Runtime::Function* f, int arg_count);
=======================================
--- /branches/bleeding_edge/src/runtime.cc Thu Apr 8 05:37:10 2010
+++ /branches/bleeding_edge/src/runtime.cc Mon Apr 12 00:05:24 2010
@@ -1361,6 +1361,13 @@
return *holder;
}
+
+
+static Object* Runtime_GetGlobalReceiver(Arguments args) {
+ // Returns a real global receiver, not one of builtins object.
+ Context* global_context = Top::context()->global()->global_context();
+ return global_context->global()->global_receiver();
+}
static Object* Runtime_MaterializeRegExpLiteral(Arguments args) {
=======================================
--- /branches/bleeding_edge/src/runtime.h Wed Apr 7 04:13:05 2010
+++ /branches/bleeding_edge/src/runtime.h Mon Apr 12 00:05:24 2010
@@ -62,6 +62,7 @@
F(ToSlowProperties, 1, 1) \
F(FinishArrayPrototypeSetup, 1, 1) \
F(SpecialArrayFunctions, 1, 1) \
+ F(GetGlobalReceiver, 0, 1) \
\
F(IsInPrototypeChain, 2, 1) \
F(SetHiddenPrototype, 2, 1) \
=======================================
--- /branches/bleeding_edge/src/x64/codegen-x64.cc Thu Apr 8 06:41:11 2010
+++ /branches/bleeding_edge/src/x64/codegen-x64.cc Mon Apr 12 00:05:24 2010
@@ -4138,6 +4138,22 @@
Result result = frame_->CallStub(&stub, 1);
frame_->Push(&result);
}
+
+
+void CodeGenerator::GenerateCallFunction(ZoneList<Expression*>* args) {
+ Comment cmnt(masm_, "[ GenerateCallFunction");
+
+ ASSERT(args->length() >= 2);
+
+ int n_args = args->length() - 2; // for receiver and function.
+ Load(args->at(0)); // receiver
+ for (int i = 0; i < n_args; i++) {
+ Load(args->at(i + 1));
+ }
+ Load(args->at(n_args + 1)); // function
+ Result result = frame_->CallJSFunction(n_args);
+ frame_->Push(&result);
+}
void CodeGenerator::GenerateMathSin(ZoneList<Expression*>* args) {
=======================================
--- /branches/bleeding_edge/src/x64/codegen-x64.h Wed Apr 7 01:18:51 2010
+++ /branches/bleeding_edge/src/x64/codegen-x64.h Mon Apr 12 00:05:24 2010
@@ -585,6 +585,9 @@
// Fast support for number to string.
void GenerateNumberToString(ZoneList<Expression*>* args);
+ // Fast call for custom callbacks.
+ void GenerateCallFunction(ZoneList<Expression*>* args);
+
// Fast call to math functions.
void GenerateMathPow(ZoneList<Expression*>* args);
void GenerateMathSin(ZoneList<Expression*>* args);
=======================================
--- /branches/bleeding_edge/src/x64/virtual-frame-x64.cc Thu Mar 25
05:44:15 2010
+++ /branches/bleeding_edge/src/x64/virtual-frame-x64.cc Mon Apr 12
00:05:24 2010
@@ -822,6 +822,25 @@
arg1->Unuse();
return RawCallStub(stub);
}
+
+
+Result VirtualFrame::CallJSFunction(int arg_count) {
+ Result function = Pop();
+
+ // InvokeFunction requires function in rdi. Move it in there.
+ function.ToRegister(rdi);
+ function.Unuse();
+
+ // +1 for receiver.
+ PrepareForCall(arg_count + 1, arg_count + 1);
+ ASSERT(cgen()->HasValidEntryRegisters());
+ ParameterCount count(arg_count);
+ __ InvokeFunction(rdi, count, CALL_FUNCTION);
+ RestoreContextRegister();
+ Result result = cgen()->allocator()->Allocate(rax);
+ ASSERT(result.is_valid());
+ return result;
+}
void VirtualFrame::SyncElementBelowStackPointer(int index) {
=======================================
--- /branches/bleeding_edge/src/x64/virtual-frame-x64.h Thu Mar 25 06:18:00
2010
+++ /branches/bleeding_edge/src/x64/virtual-frame-x64.h Mon Apr 12 00:05:24
2010
@@ -318,6 +318,10 @@
// arguments are consumed by the call.
Result CallStub(CodeStub* stub, Result* arg0, Result* arg1);
+ // Call JS function from top of the stack with arguments
+ // taken from the stack.
+ Result CallJSFunction(int arg_count);
+
// Call runtime given the number of arguments expected on (and
// removed from) the stack.
Result CallRuntime(Runtime::Function* f, int arg_count);
=======================================
--- /branches/bleeding_edge/test/mjsunit/fuzz-natives.js Thu Mar 11
01:27:12 2010
+++ /branches/bleeding_edge/test/mjsunit/fuzz-natives.js Mon Apr 12
00:05:24 2010
@@ -160,6 +160,9 @@
// That can only be invoked on Array.prototype.
"FinishArrayPrototypeSetup": true,
+ // Performance critical function which cannot afford type checks.
+ "_CallFunction": true,
+
// LiveEdit feature is under development currently and has fragile input.
"LiveEditFindSharedFunctionInfosForScript": true,
"LiveEditGatherCompileInfo": true,
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
To unsubscribe, reply using "remove me" as the subject.