Stop adapting the arguments passed to the builtin implementations
of Array.prototype.push and Array.prototype.pop. Avoid going through the arguments adaptor trampoline for call ICs that end up calling a builtin that does not need arguments adaption. Review URL: http://codereview.chromium.org/2884 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@312 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
64923a6a83
commit
3f67d5b90f
@ -291,8 +291,7 @@ class Genesis BASE_EMBEDDED {
|
|||||||
|
|
||||||
void AddSpecialFunction(Handle<JSObject> prototype,
|
void AddSpecialFunction(Handle<JSObject> prototype,
|
||||||
const char* name,
|
const char* name,
|
||||||
Handle<Code> code,
|
Handle<Code> code);
|
||||||
int parameter_count);
|
|
||||||
|
|
||||||
void BuildSpecialFunctionTable();
|
void BuildSpecialFunctionTable();
|
||||||
|
|
||||||
@ -1266,8 +1265,7 @@ void Genesis::MakeFunctionInstancePrototypeWritable() {
|
|||||||
|
|
||||||
void Genesis::AddSpecialFunction(Handle<JSObject> prototype,
|
void Genesis::AddSpecialFunction(Handle<JSObject> prototype,
|
||||||
const char* name,
|
const char* name,
|
||||||
Handle<Code> code,
|
Handle<Code> code) {
|
||||||
int parameter_count) {
|
|
||||||
Handle<String> key = Factory::LookupAsciiSymbol(name);
|
Handle<String> key = Factory::LookupAsciiSymbol(name);
|
||||||
Handle<Object> value = Handle<Object>(prototype->GetProperty(*key));
|
Handle<Object> value = Handle<Object>(prototype->GetProperty(*key));
|
||||||
if (value->IsJSFunction()) {
|
if (value->IsJSFunction()) {
|
||||||
@ -1276,7 +1274,7 @@ void Genesis::AddSpecialFunction(Handle<JSObject> prototype,
|
|||||||
JSObject::kHeaderSize,
|
JSObject::kHeaderSize,
|
||||||
code,
|
code,
|
||||||
false);
|
false);
|
||||||
optimized->shared()->set_formal_parameter_count(parameter_count);
|
optimized->shared()->DontAdaptArguments();
|
||||||
int len = global_context()->special_function_table()->length();
|
int len = global_context()->special_function_table()->length();
|
||||||
Handle<FixedArray> new_array = Factory::NewFixedArray(len + 3);
|
Handle<FixedArray> new_array = Factory::NewFixedArray(len + 3);
|
||||||
for (int index = 0; index < len; index++) {
|
for (int index = 0; index < len; index++) {
|
||||||
@ -1301,11 +1299,9 @@ void Genesis::BuildSpecialFunctionTable() {
|
|||||||
Handle<JSObject> prototype =
|
Handle<JSObject> prototype =
|
||||||
Handle<JSObject>(JSObject::cast(function->prototype()));
|
Handle<JSObject>(JSObject::cast(function->prototype()));
|
||||||
AddSpecialFunction(prototype, "pop",
|
AddSpecialFunction(prototype, "pop",
|
||||||
Handle<Code>(Builtins::builtin(Builtins::ArrayPop)),
|
Handle<Code>(Builtins::builtin(Builtins::ArrayPop)));
|
||||||
0);
|
|
||||||
AddSpecialFunction(prototype, "push",
|
AddSpecialFunction(prototype, "push",
|
||||||
Handle<Code>(Builtins::builtin(Builtins::ArrayPush)),
|
Handle<Code>(Builtins::builtin(Builtins::ArrayPush)));
|
||||||
1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -40,12 +40,21 @@ namespace v8 { namespace internal {
|
|||||||
void Builtins::Generate_Adaptor(MacroAssembler* masm,
|
void Builtins::Generate_Adaptor(MacroAssembler* masm,
|
||||||
int argc,
|
int argc,
|
||||||
CFunctionId id) {
|
CFunctionId id) {
|
||||||
// r0 contains the number of arguments excluding the receiver.
|
// TODO(1238487): Don't pass the function in a static variable.
|
||||||
// JumpToBuiltin expects r0 to contains the number of arguments
|
|
||||||
// including the receiver.
|
|
||||||
__ mov(r0, Operand(argc + 1));
|
|
||||||
__ mov(ip, Operand(ExternalReference::builtin_passed_function()));
|
__ mov(ip, Operand(ExternalReference::builtin_passed_function()));
|
||||||
__ str(r1, MemOperand(ip, 0));
|
__ str(r1, MemOperand(ip, 0));
|
||||||
|
|
||||||
|
if (argc == -1) {
|
||||||
|
// The actual argument count has already been loaded into register
|
||||||
|
// r0, but JumpToBuiltin expects r0 to contain the number of
|
||||||
|
// arguments including the receiver.
|
||||||
|
__ add(r0, r0, Operand(1));
|
||||||
|
} else {
|
||||||
|
// The number passed in argc excludes the receiver, but
|
||||||
|
// JumpToBuiltin expects r0 to contain the number of arguments
|
||||||
|
// including the receiver.
|
||||||
|
__ mov(r0, Operand(argc + 1));
|
||||||
|
}
|
||||||
__ JumpToBuiltin(ExternalReference(id));
|
__ JumpToBuiltin(ExternalReference(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,12 +40,21 @@ namespace v8 { namespace internal {
|
|||||||
void Builtins::Generate_Adaptor(MacroAssembler* masm,
|
void Builtins::Generate_Adaptor(MacroAssembler* masm,
|
||||||
int argc,
|
int argc,
|
||||||
CFunctionId id) {
|
CFunctionId id) {
|
||||||
// argc is the number of arguments excluding the receiver.
|
// TODO(1238487): Don't pass the function in a static variable.
|
||||||
// JumpToBuiltin expects eax to contain the number of arguments
|
ExternalReference passed = ExternalReference::builtin_passed_function();
|
||||||
// including the receiver.
|
__ mov(Operand::StaticVariable(passed), edi);
|
||||||
__ mov(eax, argc + 1);
|
|
||||||
__ mov(Operand::StaticVariable(ExternalReference::builtin_passed_function()),
|
if (argc == -1) {
|
||||||
edi);
|
// The actual argument count has already been loaded into register
|
||||||
|
// eax, but JumpToBuiltin expects eax to contain the number of
|
||||||
|
// arguments including the receiver.
|
||||||
|
__ inc(eax);
|
||||||
|
} else {
|
||||||
|
// The number passed in argc excludes the receiver, but
|
||||||
|
// JumpToBuiltin expects eax to contain the number of arguments
|
||||||
|
// including the receiver.
|
||||||
|
__ mov(eax, argc + 1);
|
||||||
|
}
|
||||||
__ JumpToBuiltin(ExternalReference(id));
|
__ JumpToBuiltin(ExternalReference(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,7 +67,7 @@ namespace v8 { namespace internal {
|
|||||||
// and start calling the builtins in a more direct way. Looking at the
|
// and start calling the builtins in a more direct way. Looking at the
|
||||||
// stack frames for all builtin invocations comes with a pretty
|
// stack frames for all builtin invocations comes with a pretty
|
||||||
// significant performance penalty.
|
// significant performance penalty.
|
||||||
#define BUILTIN_0(name) \
|
#define BUILTIN(name) \
|
||||||
static Object* Builtin_##name(int __argc__, \
|
static Object* Builtin_##name(int __argc__, \
|
||||||
Object** __argv__) { \
|
Object** __argv__) { \
|
||||||
Handle<Object> receiver(&__argv__[0]); \
|
Handle<Object> receiver(&__argv__[0]); \
|
||||||
@ -95,19 +95,13 @@ namespace v8 { namespace internal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#define BUILTIN_1(name, a0) \
|
// We're transitioning to a much simpler builtins framework where all
|
||||||
BUILTIN_0(name) \
|
// builtins are called *without* arguments adaption. For now, only a
|
||||||
Object* a0 = BUILTIN_ARG(1);
|
// few of the builtins have been rewritten to support this and they
|
||||||
|
// all use the NEW_BUILTIN macro instead of plain old BUILTIN.
|
||||||
|
#define NEW_BUILTIN(name) \
|
||||||
#define BUILTIN_2(name, a0, a1) \
|
static Object* Builtin_##name(int __argc__, Object** __argv__) { \
|
||||||
BUILTIN_1(name, a0) \
|
Handle<Object> receiver(&__argv__[0]);
|
||||||
Object* a1 = BUILTIN_ARG(2);
|
|
||||||
|
|
||||||
|
|
||||||
#define BUILTIN_3(name, a0, a1, a2) \
|
|
||||||
BUILTIN_2(name, a0, a1) \
|
|
||||||
Object* a2 = BUILTIN_ARG(3);
|
|
||||||
|
|
||||||
|
|
||||||
// Use an inline function to avoid evaluating the index (n) more than
|
// Use an inline function to avoid evaluating the index (n) more than
|
||||||
@ -172,18 +166,18 @@ Handle<Code> Builtins::GetCode(JavaScript id, bool* resolved) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BUILTIN_0(Illegal) {
|
BUILTIN(Illegal) {
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
BUILTIN_END
|
BUILTIN_END
|
||||||
|
|
||||||
|
|
||||||
BUILTIN_0(EmptyFunction) {
|
BUILTIN(EmptyFunction) {
|
||||||
}
|
}
|
||||||
BUILTIN_END
|
BUILTIN_END
|
||||||
|
|
||||||
|
|
||||||
BUILTIN_0(ArrayCode) {
|
BUILTIN(ArrayCode) {
|
||||||
JSArray* array;
|
JSArray* array;
|
||||||
if (is_construct) {
|
if (is_construct) {
|
||||||
array = JSArray::cast(*receiver);
|
array = JSArray::cast(*receiver);
|
||||||
@ -241,7 +235,7 @@ BUILTIN_0(ArrayCode) {
|
|||||||
BUILTIN_END
|
BUILTIN_END
|
||||||
|
|
||||||
|
|
||||||
BUILTIN_0(ArrayPush) {
|
NEW_BUILTIN(ArrayPush) {
|
||||||
JSArray* array = JSArray::cast(*receiver);
|
JSArray* array = JSArray::cast(*receiver);
|
||||||
ASSERT(array->HasFastElements());
|
ASSERT(array->HasFastElements());
|
||||||
|
|
||||||
@ -280,7 +274,7 @@ BUILTIN_0(ArrayPush) {
|
|||||||
BUILTIN_END
|
BUILTIN_END
|
||||||
|
|
||||||
|
|
||||||
BUILTIN_0(ArrayPop) {
|
NEW_BUILTIN(ArrayPop) {
|
||||||
JSArray* array = JSArray::cast(*receiver);
|
JSArray* array = JSArray::cast(*receiver);
|
||||||
ASSERT(array->HasFastElements());
|
ASSERT(array->HasFastElements());
|
||||||
Object* undefined = Heap::undefined_value();
|
Object* undefined = Heap::undefined_value();
|
||||||
@ -365,7 +359,7 @@ static inline Object* TypeCheck(int argc,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BUILTIN_0(HandleApiCall) {
|
BUILTIN(HandleApiCall) {
|
||||||
HandleScope scope;
|
HandleScope scope;
|
||||||
|
|
||||||
// TODO(1238487): This is not nice. We need to get rid of this
|
// TODO(1238487): This is not nice. We need to get rid of this
|
||||||
@ -445,7 +439,7 @@ BUILTIN_END
|
|||||||
|
|
||||||
// Handle calls to non-function objects created through the API that
|
// Handle calls to non-function objects created through the API that
|
||||||
// support calls.
|
// support calls.
|
||||||
BUILTIN_0(HandleApiCallAsFunction) {
|
BUILTIN(HandleApiCallAsFunction) {
|
||||||
// Non-functions are never called as constructors.
|
// Non-functions are never called as constructors.
|
||||||
ASSERT(!is_construct);
|
ASSERT(!is_construct);
|
||||||
|
|
||||||
|
@ -38,8 +38,8 @@ namespace v8 { namespace internal {
|
|||||||
\
|
\
|
||||||
V(ArrayCode, 0) \
|
V(ArrayCode, 0) \
|
||||||
\
|
\
|
||||||
V(ArrayPush, 1) \
|
V(ArrayPush, -1) \
|
||||||
V(ArrayPop, 0) \
|
V(ArrayPop, -1) \
|
||||||
\
|
\
|
||||||
V(HandleApiCall, 0) \
|
V(HandleApiCall, 0) \
|
||||||
V(HandleApiCallAsFunction, 0)
|
V(HandleApiCallAsFunction, 0)
|
||||||
|
@ -299,7 +299,16 @@ void MacroAssembler::InvokePrologue(const ParameterCount& expected,
|
|||||||
definitely_matches = true;
|
definitely_matches = true;
|
||||||
} else {
|
} else {
|
||||||
mov(r0, Operand(actual.immediate()));
|
mov(r0, Operand(actual.immediate()));
|
||||||
mov(r2, Operand(expected.immediate()));
|
const int sentinel = SharedFunctionInfo::kDontAdaptArgumentsSentinel;
|
||||||
|
if (expected.immediate() == sentinel) {
|
||||||
|
// Don't worry about adapting arguments for builtins that
|
||||||
|
// don't want that done. Skip adaption code by making it look
|
||||||
|
// like we have a match between expected and actual number of
|
||||||
|
// arguments.
|
||||||
|
definitely_matches = true;
|
||||||
|
} else {
|
||||||
|
mov(r2, Operand(expected.immediate()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (actual.is_immediate()) {
|
if (actual.is_immediate()) {
|
||||||
|
@ -572,7 +572,16 @@ void MacroAssembler::InvokePrologue(const ParameterCount& expected,
|
|||||||
definitely_matches = true;
|
definitely_matches = true;
|
||||||
} else {
|
} else {
|
||||||
mov(eax, actual.immediate());
|
mov(eax, actual.immediate());
|
||||||
mov(ebx, expected.immediate());
|
const int sentinel = SharedFunctionInfo::kDontAdaptArgumentsSentinel;
|
||||||
|
if (expected.immediate() == sentinel) {
|
||||||
|
// Don't worry about adapting arguments for builtins that
|
||||||
|
// don't want that done. Skip adaption code by making it look
|
||||||
|
// like we have a match between expected and actual number of
|
||||||
|
// arguments.
|
||||||
|
definitely_matches = true;
|
||||||
|
} else {
|
||||||
|
mov(ebx, expected.immediate());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (actual.is_immediate()) {
|
if (actual.is_immediate()) {
|
||||||
|
@ -1783,6 +1783,7 @@ INT_ACCESSORS(SharedFunctionInfo, function_token_position,
|
|||||||
|
|
||||||
|
|
||||||
void SharedFunctionInfo::DontAdaptArguments() {
|
void SharedFunctionInfo::DontAdaptArguments() {
|
||||||
|
ASSERT(code()->kind() == Code::BUILTIN);
|
||||||
set_formal_parameter_count(kDontAdaptArgumentsSentinel);
|
set_formal_parameter_count(kDontAdaptArgumentsSentinel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user