| Index: src/builtins.cc
|
| ===================================================================
|
| --- src/builtins.cc (revision 312)
|
| +++ src/builtins.cc (working copy)
|
| @@ -40,16 +40,13 @@
|
| //
|
| // 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 @@
|
| // ----------------------------------------------------------------------------
|
|
|
|
|
| -// 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 @@
|
| }
|
|
|
|
|
| +// 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(ArrayCode) {
|
| JSArray* array;
|
| - if (is_construct) {
|
| + if (CalledAsConstructor()) {
|
| array = JSArray::cast(*receiver);
|
| } else {
|
| // Allocate the JS Array
|
| @@ -235,7 +212,7 @@
|
| BUILTIN_END
|
|
|
|
|
| -NEW_BUILTIN(ArrayPush) {
|
| +BUILTIN(ArrayPush) {
|
| JSArray* array = JSArray::cast(*receiver);
|
| ASSERT(array->HasFastElements());
|
|
|
| @@ -274,7 +251,7 @@
|
| BUILTIN_END
|
|
|
|
|
| -NEW_BUILTIN(ArrayPop) {
|
| +BUILTIN(ArrayPop) {
|
| JSArray* array = JSArray::cast(*receiver);
|
| ASSERT(array->HasFastElements());
|
| Object* undefined = Heap::undefined_value();
|
| @@ -361,6 +338,7 @@
|
|
|
| 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 @@
|
| // 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 @@
|
| data,
|
| self,
|
| callee,
|
| - is_construct,
|
| + false,
|
| reinterpret_cast<void**>(__argv__ - 1),
|
| __argc__ - 1);
|
| v8::Handle<v8::Value> value;
|
| @@ -606,7 +584,7 @@
|
| 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 @@
|
| 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 @@
|
| 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 @@
|
| 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 @@
|
| 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);
|
|
|