New version of v8 from bleeding edge at revision 3649
diff --git a/src/builtins.cc b/src/builtins.cc
index b66635c..9db2230 100644
--- a/src/builtins.cc
+++ b/src/builtins.cc
@@ -36,8 +36,78 @@
 namespace v8 {
 namespace internal {
 
+namespace {
+
+// Arguments object passed to C++ builtins.
+template <BuiltinExtraArguments extra_args>
+class BuiltinArguments : public Arguments {
+ public:
+  BuiltinArguments(int length, Object** arguments)
+      : Arguments(length, arguments) { }
+
+  Object*& operator[] (int index) {
+    ASSERT(index < length());
+    return Arguments::operator[](index);
+  }
+
+  template <class S> Handle<S> at(int index) {
+    ASSERT(index < length());
+    return Arguments::at<S>(index);
+  }
+
+  Handle<Object> receiver() {
+    return Arguments::at<Object>(0);
+  }
+
+  Handle<JSFunction> called_function() {
+    STATIC_ASSERT(extra_args == NEEDS_CALLED_FUNCTION);
+    return Arguments::at<JSFunction>(Arguments::length() - 1);
+  }
+
+  // Gets the total number of arguments including the receiver (but
+  // excluding extra arguments).
+  int length() const {
+    STATIC_ASSERT(extra_args == NO_EXTRA_ARGUMENTS);
+    return Arguments::length();
+  }
+
+#ifdef DEBUG
+  void Verify() {
+    // Check we have at least the receiver.
+    ASSERT(Arguments::length() >= 1);
+  }
+#endif
+};
+
+
+// Specialize BuiltinArguments for the called function extra argument.
+
+template <>
+int BuiltinArguments<NEEDS_CALLED_FUNCTION>::length() const {
+  return Arguments::length() - 1;
+}
+
+#ifdef DEBUG
+template <>
+void BuiltinArguments<NEEDS_CALLED_FUNCTION>::Verify() {
+  // Check we have at least the receiver and the called function.
+  ASSERT(Arguments::length() >= 2);
+  // Make sure cast to JSFunction succeeds.
+  called_function();
+}
+#endif
+
+
+#define DEF_ARG_TYPE(name, spec)                      \
+  typedef BuiltinArguments<spec> name##ArgumentsType;
+BUILTIN_LIST_C(DEF_ARG_TYPE)
+#undef DEF_ARG_TYPE
+
+}  // namespace
+
+
 // ----------------------------------------------------------------------------
-// Support macros for defining builtins in C.
+// Support macro for defining builtins in C++.
 // ----------------------------------------------------------------------------
 //
 // A builtin function is defined by writing:
@@ -45,30 +115,26 @@
 //   BUILTIN(name) {
 //     ...
 //   }
-//   BUILTIN_END
 //
-// In the body of the builtin function, the variable 'receiver' is visible.
-// The arguments can be accessed through the Arguments object args.
-//
-//   args[0]: Receiver (also available as 'receiver')
-//   args[1]: First argument
-//     ...
-//   args[n]: Last argument
-//   args.length(): Number of arguments including the receiver.
-// ----------------------------------------------------------------------------
+// In the body of the builtin function the arguments can be accessed
+// through the BuiltinArguments object args.
 
+#ifdef DEBUG
 
-// TODO(428): 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(Arguments args) {      \
-    Handle<Object> receiver = args.at<Object>(0);
+#define BUILTIN(name)                                           \
+  static Object* Builtin_Impl_##name(name##ArgumentsType args); \
+  static Object* Builtin_##name(name##ArgumentsType args) {     \
+    args.Verify();                                              \
+    return Builtin_Impl_##name(args);                           \
+  }                                                             \
+  static Object* Builtin_Impl_##name(name##ArgumentsType args)
 
+#else  // For release mode.
 
-#define BUILTIN_END                             \
-  return Heap::undefined_value();               \
-}
+#define BUILTIN(name)                                           \
+  static Object* Builtin_##name(name##ArgumentsType args)
+
+#endif
 
 
 static inline bool CalledAsConstructor() {
@@ -126,13 +192,13 @@
 
 BUILTIN(Illegal) {
   UNREACHABLE();
+  return Heap::undefined_value();  // Make compiler happy.
 }
-BUILTIN_END
 
 
 BUILTIN(EmptyFunction) {
+  return Heap::undefined_value();
 }
-BUILTIN_END
 
 
 BUILTIN(ArrayCodeGeneric) {
@@ -140,7 +206,7 @@
 
   JSArray* array;
   if (CalledAsConstructor()) {
-    array = JSArray::cast(*receiver);
+    array = JSArray::cast(*args.receiver());
   } else {
     // Allocate the JS Array
     JSFunction* constructor =
@@ -194,11 +260,10 @@
 
   return array;
 }
-BUILTIN_END
 
 
 BUILTIN(ArrayPush) {
-  JSArray* array = JSArray::cast(*receiver);
+  JSArray* array = JSArray::cast(*args.receiver());
   ASSERT(array->HasFastElements());
 
   // Make sure we have space for the elements.
@@ -233,11 +298,10 @@
   array->set_length(Smi::FromInt(new_length), SKIP_WRITE_BARRIER);
   return array->length();
 }
-BUILTIN_END
 
 
 BUILTIN(ArrayPop) {
-  JSArray* array = JSArray::cast(*receiver);
+  JSArray* array = JSArray::cast(*args.receiver());
   ASSERT(array->HasFastElements());
   Object* undefined = Heap::undefined_value();
 
@@ -265,7 +329,6 @@
 
   return top;
 }
-BUILTIN_END
 
 
 // -----------------------------------------------------------------------------
@@ -320,20 +383,20 @@
 }
 
 
-BUILTIN(HandleApiCall) {
-  HandleScope scope;
-  bool is_construct = CalledAsConstructor();
+template <bool is_construct>
+static Object* HandleApiCallHelper(
+    BuiltinArguments<NEEDS_CALLED_FUNCTION> args) {
+  ASSERT(is_construct == CalledAsConstructor());
 
-  // TODO(428): Remove use of static variable, handle API callbacks directly.
-  Handle<JSFunction> function =
-      Handle<JSFunction>(JSFunction::cast(Builtins::builtin_passed_function));
+  HandleScope scope;
+  Handle<JSFunction> function = args.called_function();
 
   if (is_construct) {
     Handle<FunctionTemplateInfo> desc =
         Handle<FunctionTemplateInfo>(
             FunctionTemplateInfo::cast(function->shared()->function_data()));
     bool pending_exception = false;
-    Factory::ConfigureInstance(desc, Handle<JSObject>::cast(receiver),
+    Factory::ConfigureInstance(desc, Handle<JSObject>::cast(args.receiver()),
                                &pending_exception);
     ASSERT(Top::has_pending_exception() == pending_exception);
     if (pending_exception) return Failure::Exception();
@@ -359,15 +422,13 @@
     Object* data_obj = call_data->data();
     Object* result;
 
-    v8::Local<v8::Object> self =
-        v8::Utils::ToLocal(Handle<JSObject>::cast(receiver));
     Handle<Object> data_handle(data_obj);
     v8::Local<v8::Value> data = v8::Utils::ToLocal(data_handle);
     ASSERT(raw_holder->IsJSObject());
     v8::Local<v8::Function> callee = v8::Utils::ToLocal(function);
     Handle<JSObject> holder_handle(JSObject::cast(raw_holder));
     v8::Local<v8::Object> holder = v8::Utils::ToLocal(holder_handle);
-    LOG(ApiObjectAccess("call", JSObject::cast(*receiver)));
+    LOG(ApiObjectAccess("call", JSObject::cast(*args.receiver())));
     v8::Arguments new_args = v8::ImplementationUtilities::NewArguments(
         data,
         holder,
@@ -395,16 +456,26 @@
     if (!is_construct || result->IsJSObject()) return result;
   }
 
-  return *receiver;
+  return *args.receiver();
 }
-BUILTIN_END
+
+
+BUILTIN(HandleApiCall) {
+  return HandleApiCallHelper<false>(args);
+}
+
+
+BUILTIN(HandleApiCallConstruct) {
+  return HandleApiCallHelper<true>(args);
+}
 
 
 // Helper function to handle calls to non-function objects created through the
 // API. The object can be called as either a constructor (using new) or just as
 // a function (without new).
-static Object* HandleApiCallAsFunctionOrConstructor(bool is_construct_call,
-                                                    Arguments args) {
+static Object* HandleApiCallAsFunctionOrConstructor(
+    bool is_construct_call,
+    BuiltinArguments<NO_EXTRA_ARGUMENTS> args) {
   // Non-functions are never called as constructors. Even if this is an object
   // called as a constructor the delegate call is not a construct call.
   ASSERT(!CalledAsConstructor());
@@ -412,7 +483,7 @@
   Handle<Object> receiver = args.at<Object>(0);
 
   // Get the object called.
-  JSObject* obj = JSObject::cast(*receiver);
+  JSObject* obj = JSObject::cast(*args.receiver());
 
   // Get the invocation callback from the function descriptor that was
   // used to create the called object.
@@ -432,12 +503,12 @@
   Object* result;
   { HandleScope scope;
     v8::Local<v8::Object> self =
-        v8::Utils::ToLocal(Handle<JSObject>::cast(receiver));
+        v8::Utils::ToLocal(Handle<JSObject>::cast(args.receiver()));
     Handle<Object> data_handle(data_obj);
     v8::Local<v8::Value> data = v8::Utils::ToLocal(data_handle);
     Handle<JSFunction> callee_handle(constructor);
     v8::Local<v8::Function> callee = v8::Utils::ToLocal(callee_handle);
-    LOG(ApiObjectAccess("call non-function", JSObject::cast(*receiver)));
+    LOG(ApiObjectAccess("call non-function", JSObject::cast(*args.receiver())));
     v8::Arguments new_args = v8::ImplementationUtilities::NewArguments(
         data,
         self,
@@ -471,7 +542,6 @@
 BUILTIN(HandleApiCallAsFunction) {
   return HandleApiCallAsFunctionOrConstructor(false, args);
 }
-BUILTIN_END
 
 
 // Handle calls to non-function objects created through the API. This delegate
@@ -479,14 +549,6 @@
 BUILTIN(HandleApiCallAsConstructor) {
   return HandleApiCallAsFunctionOrConstructor(true, args);
 }
-BUILTIN_END
-
-
-// TODO(1238487): This is a nasty hack. We need to improve the way we
-// call builtins considerable to get rid of this and the hairy macros
-// in builtins.cc.
-Object* Builtins::builtin_passed_function;
-
 
 
 static void Generate_LoadIC_ArrayLength(MacroAssembler* masm) {
@@ -544,6 +606,11 @@
 }
 
 
+static void Generate_KeyedLoadIC_String(MacroAssembler* masm) {
+  KeyedLoadIC::GenerateString(masm);
+}
+
+
 static void Generate_KeyedLoadIC_ExternalByteArray(MacroAssembler* masm) {
   KeyedLoadIC::GenerateExternalArray(masm, kExternalByteArray);
 }
@@ -703,7 +770,7 @@
 Object* Builtins::builtins_[builtin_count] = { NULL, };
 const char* Builtins::names_[builtin_count] = { NULL, };
 
-#define DEF_ENUM_C(name) FUNCTION_ADDR(Builtin_##name),
+#define DEF_ENUM_C(name, ignore) FUNCTION_ADDR(Builtin_##name),
   Address Builtins::c_functions_[cfunction_count] = {
     BUILTIN_LIST_C(DEF_ENUM_C)
   };
@@ -734,14 +801,16 @@
     const char* s_name;  // name is only used for generating log information.
     int name;
     Code::Flags flags;
+    BuiltinExtraArguments extra_args;
   };
 
-#define DEF_FUNCTION_PTR_C(name)         \
-    { FUNCTION_ADDR(Generate_Adaptor),   \
-      FUNCTION_ADDR(Builtin_##name),     \
-      #name,                             \
-      c_##name,                          \
-      Code::ComputeFlags(Code::BUILTIN)  \
+#define DEF_FUNCTION_PTR_C(name, extra_args) \
+    { FUNCTION_ADDR(Generate_Adaptor),            \
+      FUNCTION_ADDR(Builtin_##name),              \
+      #name,                                      \
+      c_##name,                                   \
+      Code::ComputeFlags(Code::BUILTIN),          \
+      extra_args                                  \
     },
 
 #define DEF_FUNCTION_PTR_A(name, kind, state)              \
@@ -749,7 +818,8 @@
       NULL,                                                \
       #name,                                               \
       name,                                                \
-      Code::ComputeFlags(Code::kind, NOT_IN_LOOP, state)   \
+      Code::ComputeFlags(Code::kind, NOT_IN_LOOP, state),  \
+      NO_EXTRA_ARGUMENTS                                   \
     },
 
   // Define array of pointers to generators and C builtin functions.
@@ -758,7 +828,8 @@
       BUILTIN_LIST_A(DEF_FUNCTION_PTR_A)
       BUILTIN_LIST_DEBUG_A(DEF_FUNCTION_PTR_A)
       // Terminator:
-      { NULL, NULL, NULL, builtin_count, static_cast<Code::Flags>(0) }
+      { NULL, NULL, NULL, builtin_count, static_cast<Code::Flags>(0),
+        NO_EXTRA_ARGUMENTS }
   };
 
 #undef DEF_FUNCTION_PTR_C
@@ -774,12 +845,12 @@
     if (create_heap_objects) {
       MacroAssembler masm(buffer, sizeof buffer);
       // Generate the code/adaptor.
-      typedef void (*Generator)(MacroAssembler*, int);
+      typedef void (*Generator)(MacroAssembler*, int, BuiltinExtraArguments);
       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].name);
+      g(&masm, functions[i].name, functions[i].extra_args);
       // Move the code into the object heap.
       CodeDesc desc;
       masm.GetCode(&desc);