Remove the old builtins framework with the huge, nasty

macro.
Review URL: http://codereview.chromium.org/3079

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@314 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
kasperl@chromium.org 2008-09-16 10:12:32 +00:00
parent ec5a24dd64
commit 725dcfb503
8 changed files with 63 additions and 103 deletions

View File

@ -486,14 +486,15 @@ void Genesis::CreateRoots(v8::Handle<v8::ObjectTemplate> global_template,
Factory::NewFunction(symbol, Factory::null_value());
{ // --- E m p t y ---
Handle<Code> call_code =
Handle<Code> code =
Handle<Code>(Builtins::builtin(Builtins::EmptyFunction));
Handle<String> source = Factory::NewStringFromAscii(CStrVector("() {}"));
empty_function->set_code(*call_code);
empty_function->set_code(*code);
empty_function->shared()->set_script(*Factory::NewScript(source));
empty_function->shared()->set_start_position(0);
empty_function->shared()->set_end_position(source->length());
empty_function->shared()->DontAdaptArguments();
global_context()->function_map()->set_prototype(*empty_function);
global_context()->function_instance_map()->set_prototype(*empty_function);
@ -580,6 +581,7 @@ 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()->DontAdaptArguments();
// This seems a bit hackish, but we need to make sure Array.length
// is 1.
@ -709,6 +711,7 @@ void Genesis::CreateRoots(v8::Handle<v8::ObjectTemplate> global_template,
Factory::NewFunction(Factory::empty_symbol(), JS_OBJECT_TYPE,
JSObject::kHeaderSize, code, true);
global_context()->set_call_as_function_delegate(*delegate);
delegate->shared()->DontAdaptArguments();
global_context()->set_special_function_table(Heap::empty_fixed_array());

View File

@ -37,24 +37,15 @@ namespace v8 { namespace internal {
#define __ masm->
void Builtins::Generate_Adaptor(MacroAssembler* masm,
int argc,
CFunctionId id) {
void Builtins::Generate_Adaptor(MacroAssembler* masm, CFunctionId id) {
// TODO(1238487): Don't pass the function in a static variable.
__ mov(ip, Operand(ExternalReference::builtin_passed_function()));
__ 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));
}
// 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));
__ JumpToBuiltin(ExternalReference(id));
}

View File

@ -37,24 +37,15 @@ namespace v8 { namespace internal {
#define __ masm->
void Builtins::Generate_Adaptor(MacroAssembler* masm,
int argc,
CFunctionId id) {
void Builtins::Generate_Adaptor(MacroAssembler* masm, CFunctionId id) {
// TODO(1238487): Don't pass the function in a static variable.
ExternalReference passed = ExternalReference::builtin_passed_function();
__ mov(Operand::StaticVariable(passed), edi);
if (argc == -1) {
// 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);
}
// 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);
__ JumpToBuiltin(ExternalReference(id));
}

View File

@ -40,16 +40,13 @@ namespace v8 { namespace internal {
//
// A builtin function is defined by writing:
//
// BUILTIN_<n>(name, ...)
// {
// BUILTIN(name) {
// ...
// }
// BUILTIN_END
//
// where <n> is the number of arguments (not counting the receiver). The
// names of the arguments must be listed after the name in the declaration.
// In the body of the builtin function, the variables 'env' and 'receiver'
// are visible. The arguments can be accessed through:
// In the body of the builtin function, the variable 'receiver' is visible.
// The arguments can be accessed through:
//
// BUILTIN_ARG(0): Receiver (also available as 'receiver')
// BUILTIN_ARG(1): First argument
@ -63,43 +60,10 @@ namespace v8 { namespace internal {
// ----------------------------------------------------------------------------
// TODO(1238487): This is not okay. We need to get rid of this macro
// and start calling the builtins in a more direct way. Looking at the
// stack frames for all builtin invocations comes with a pretty
// significant performance penalty.
// TODO(1238487): We should consider passing whether or not the
// builtin was invoked as a constructor as part of the
// arguments. Maybe we also want to pass the called function?
#define BUILTIN(name) \
static Object* Builtin_##name(int __argc__, \
Object** __argv__) { \
Handle<Object> receiver(&__argv__[0]); \
bool is_construct = false; \
USE(__argc__); \
USE(__argv__); \
{ StackFrameIterator it; \
ASSERT(it.frame()->is_exit()); \
it.Advance(); \
StackFrame::Type type = it.frame()->type(); \
if (type == StackFrame::INTERNAL) { \
InternalFrame* frame = InternalFrame::cast(it.frame()); \
is_construct = frame->is_construct_trampoline(); \
} else if (type == StackFrame::ARGUMENTS_ADAPTOR) { \
ArgumentsAdaptorFrame* frame = \
ArgumentsAdaptorFrame::cast(it.frame()); \
/* __argc__ includes the receiver. */ \
__argc__ = frame->GetProvidedParametersCount() + 1; \
__argv__ = reinterpret_cast<Object**>(frame->pp()) - 1; \
it.Advance(); \
is_construct = \
it.frame()->is_internal() && \
InternalFrame::cast(it.frame())->is_construct_trampoline(); \
} \
}
// We're transitioning to a much simpler builtins framework where all
// builtins are called *without* arguments adaption. For now, only a
// 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) \
static Object* Builtin_##name(int __argc__, Object** __argv__) { \
Handle<Object> receiver(&__argv__[0]);
@ -122,6 +86,19 @@ static inline Object* __builtin_arg__(int n, int argc, Object** argv) {
}
// TODO(1238487): Get rid of this function that determines if the
// builtin is called as a constructor. This may be a somewhat slow
// operation due to the stack frame iteration.
static inline bool CalledAsConstructor() {
StackFrameIterator it;
ASSERT(it.frame()->is_exit());
it.Advance();
StackFrame* frame = it.frame();
return frame->is_internal() &&
InternalFrame::cast(frame)->is_construct_trampoline();
}
// ----------------------------------------------------------------------------
@ -179,7 +156,7 @@ BUILTIN_END
BUILTIN(ArrayCode) {
JSArray* array;
if (is_construct) {
if (CalledAsConstructor()) {
array = JSArray::cast(*receiver);
} else {
// Allocate the JS Array
@ -235,7 +212,7 @@ BUILTIN(ArrayCode) {
BUILTIN_END
NEW_BUILTIN(ArrayPush) {
BUILTIN(ArrayPush) {
JSArray* array = JSArray::cast(*receiver);
ASSERT(array->HasFastElements());
@ -274,7 +251,7 @@ NEW_BUILTIN(ArrayPush) {
BUILTIN_END
NEW_BUILTIN(ArrayPop) {
BUILTIN(ArrayPop) {
JSArray* array = JSArray::cast(*receiver);
ASSERT(array->HasFastElements());
Object* undefined = Heap::undefined_value();
@ -361,6 +338,7 @@ static inline Object* TypeCheck(int argc,
BUILTIN(HandleApiCall) {
HandleScope scope;
bool is_construct = CalledAsConstructor();
// TODO(1238487): This is not nice. We need to get rid of this
// kludgy behavior and start handling API calls in a more direct
@ -441,7 +419,7 @@ BUILTIN_END
// support calls.
BUILTIN(HandleApiCallAsFunction) {
// Non-functions are never called as constructors.
ASSERT(!is_construct);
ASSERT(!CalledAsConstructor());
// Get the object called.
JSObject* obj = JSObject::cast(*receiver);
@ -474,7 +452,7 @@ BUILTIN(HandleApiCallAsFunction) {
data,
self,
callee,
is_construct,
false,
reinterpret_cast<void**>(__argv__ - 1),
__argc__ - 1);
v8::Handle<v8::Value> value;
@ -606,7 +584,7 @@ static void Generate_KeyedStoreIC_Initialize(MacroAssembler* masm) {
Object* Builtins::builtins_[builtin_count] = { NULL, };
const char* Builtins::names_[builtin_count] = { NULL, };
#define DEF_ENUM_C(name, ignore) FUNCTION_ADDR(Builtin_##name),
#define DEF_ENUM_C(name) FUNCTION_ADDR(Builtin_##name),
Address Builtins::c_functions_[cfunction_count] = {
BUILTIN_LIST_C(DEF_ENUM_C)
};
@ -637,16 +615,14 @@ void Builtins::Setup(bool create_heap_objects) {
const char* s_name; // name is only used for generating log information.
int name;
Code::Flags flags;
int argc;
};
#define DEF_FUNCTION_PTR_C(name, argc) \
#define DEF_FUNCTION_PTR_C(name) \
{ FUNCTION_ADDR(Generate_Adaptor), \
FUNCTION_ADDR(Builtin_##name), \
#name, \
c_##name, \
Code::ComputeFlags(Code::BUILTIN), \
argc \
Code::ComputeFlags(Code::BUILTIN) \
},
#define DEF_FUNCTION_PTR_A(name, kind, state) \
@ -654,8 +630,7 @@ void Builtins::Setup(bool create_heap_objects) {
NULL, \
#name, \
name, \
Code::ComputeFlags(Code::kind, state), \
-1 \
Code::ComputeFlags(Code::kind, state) \
},
// Define array of pointers to generators and C builtin functions.
@ -663,7 +638,7 @@ void Builtins::Setup(bool create_heap_objects) {
BUILTIN_LIST_C(DEF_FUNCTION_PTR_C)
BUILTIN_LIST_A(DEF_FUNCTION_PTR_A)
// Terminator:
{ NULL, NULL, NULL, builtin_count, static_cast<Code::Flags>(0), -1}
{ NULL, NULL, NULL, builtin_count, static_cast<Code::Flags>(0) }
};
#undef DEF_FUNCTION_PTR_C
@ -679,12 +654,12 @@ void Builtins::Setup(bool create_heap_objects) {
if (create_heap_objects) {
MacroAssembler masm(buffer, sizeof buffer);
// Generate the code/adaptor.
typedef void (*Generator)(MacroAssembler*, int, int);
typedef void (*Generator)(MacroAssembler*, int);
Generator g = FUNCTION_CAST<Generator>(functions[i].generator);
// We pass all arguments to the generator, but it may not use all of
// them. This works because the first arguments are on top of the
// stack.
g(&masm, functions[i].argc, functions[i].name);
g(&masm, functions[i].name);
// Move the code into the object heap.
CodeDesc desc;
masm.GetCode(&desc);

View File

@ -32,17 +32,17 @@ namespace v8 { namespace internal {
// Define list of builtins implemented in C.
#define BUILTIN_LIST_C(V) \
V(Illegal, 0) \
V(Illegal) \
\
V(EmptyFunction, 0) \
V(EmptyFunction) \
\
V(ArrayCode, 0) \
V(ArrayCode) \
\
V(ArrayPush, -1) \
V(ArrayPop, -1) \
V(ArrayPush) \
V(ArrayPop) \
\
V(HandleApiCall, 0) \
V(HandleApiCallAsFunction, 0)
V(HandleApiCall) \
V(HandleApiCallAsFunction)
// Define list of builtins implemented in assembly.
@ -141,7 +141,7 @@ class Builtins : public AllStatic {
static const char* Lookup(byte* pc);
enum Name {
#define DEF_ENUM_C(name, ignore) name,
#define DEF_ENUM_C(name) name,
#define DEF_ENUM_A(name, kind, state) name,
BUILTIN_LIST_C(DEF_ENUM_C)
BUILTIN_LIST_A(DEF_ENUM_A)
@ -151,7 +151,7 @@ class Builtins : public AllStatic {
};
enum CFunctionId {
#define DEF_ENUM_C(name, ignore) c_##name,
#define DEF_ENUM_C(name) c_##name,
BUILTIN_LIST_C(DEF_ENUM_C)
#undef DEF_ENUM_C
cfunction_count
@ -200,7 +200,6 @@ class Builtins : public AllStatic {
// function f, we use an Object* array here.
static Object* builtins_[builtin_count];
static const char* names_[builtin_count];
static const char* javascript_names_[id_count];
static int javascript_argc_[id_count];
@ -210,9 +209,7 @@ class Builtins : public AllStatic {
static int construct_call_pc_offset_;
static int arguments_adaptor_call_pc_offset_;
static void Generate_Adaptor(MacroAssembler* masm,
int argc,
CFunctionId id);
static void Generate_Adaptor(MacroAssembler* masm, CFunctionId id);
static void Generate_JSConstructCall(MacroAssembler* masm);
static void Generate_JSEntryTrampoline(MacroAssembler* masm);
static void Generate_JSConstructEntryTrampoline(MacroAssembler* masm);

View File

@ -727,6 +727,7 @@ Handle<JSFunction> Factory::CreateApiFunction(
}
result->shared()->set_function_data(*obj);
result->shared()->DontAdaptArguments();
// Recursively copy parent templates' accessors, 'data' may be modified.
Handle<DescriptorArray> array =

View File

@ -1138,6 +1138,8 @@ Statement* Parser::ParseNativeDeclaration(bool* ok) {
// builtins.cc:HandleApiCall to perform argument type checks and to
// find the right native code to call.
boilerplate->shared()->set_function_data(fun->shared()->function_data());
int parameters = fun->shared()->formal_parameter_count();
boilerplate->shared()->set_formal_parameter_count(parameters);
// TODO(1240846): It's weird that native function declarations are
// introduced dynamically when we meet their declarations, whereas

View File

@ -452,7 +452,7 @@ ExternalReferenceTable::ExternalReferenceTable() : refs_(64) {
// Define all entries in the table.
// Builtins
#define DEF_ENTRY_C(name, ignore) \
#define DEF_ENTRY_C(name) \
Add(Builtins::c_function_address(Builtins::c_##name), \
C_BUILTIN, \
Builtins::c_##name, \
@ -461,12 +461,12 @@ ExternalReferenceTable::ExternalReferenceTable() : refs_(64) {
BUILTIN_LIST_C(DEF_ENTRY_C)
#undef DEF_ENTRY_C
#define DEF_ENTRY_C(name, ignore) \
#define DEF_ENTRY_C(name) \
Add(Builtins::builtin_address(Builtins::name), \
BUILTIN, \
Builtins::name, \
"Builtins::" #name);
#define DEF_ENTRY_A(name, kind, state) DEF_ENTRY_C(name, _)
#define DEF_ENTRY_A(name, kind, state) DEF_ENTRY_C(name)
BUILTIN_LIST_C(DEF_ENTRY_C)
BUILTIN_LIST_A(DEF_ENTRY_A)