Refactored custom call IC generators:
authorvitalyr@chromium.org <vitalyr@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 6 May 2010 13:21:53 +0000 (13:21 +0000)
committervitalyr@chromium.org <vitalyr@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 6 May 2010 13:21:53 +0000 (13:21 +0000)
 * All generators are listed in a single place.
 * Generators are installed as a separate pass in the bootstrapper.
 * Replaced pointers to generator functions with integer ids.

Review URL: http://codereview.chromium.org/1981002

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@4606 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

12 files changed:
src/arm/stub-cache-arm.cc
src/assembler.cc
src/assembler.h
src/bootstrapper.cc
src/ia32/stub-cache-ia32.cc
src/objects-inl.h
src/objects.h
src/runtime.cc
src/serialize.cc
src/stub-cache.cc
src/stub-cache.h
src/x64/stub-cache-x64.cc

index 095631d6428cea1abe0f3a9937fdc85e994c4f14..b302fa0b939686352f3304104dab4d005f6bfa95 100644 (file)
@@ -1121,11 +1121,7 @@ Object* CallStubCompiler::CompileArrayPushCall(Object* object,
   __ Jump(ic, RelocInfo::CODE_TARGET);
 
   // Return the generated code.
-  String* function_name = NULL;
-  if (function->shared()->name()->IsString()) {
-    function_name = String::cast(function->shared()->name());
-  }
-  return GetCode(CONSTANT_FUNCTION, function_name);
+  return GetCode(function);
 }
 
 
@@ -1175,11 +1171,7 @@ Object* CallStubCompiler::CompileArrayPopCall(Object* object,
   __ Jump(ic, RelocInfo::CODE_TARGET);
 
   // Return the generated code.
-  String* function_name = NULL;
-  if (function->shared()->name()->IsString()) {
-    function_name = String::cast(function->shared()->name());
-  }
-  return GetCode(CONSTANT_FUNCTION, function_name);
+  return GetCode(function);
 }
 
 
@@ -1194,9 +1186,9 @@ Object* CallStubCompiler::CompileCallConstant(Object* object,
   // -----------------------------------
   SharedFunctionInfo* function_info = function->shared();
   if (function_info->HasCustomCallGenerator()) {
-    CustomCallGenerator generator =
-        ToCData<CustomCallGenerator>(function_info->function_data());
-    Object* result = generator(this, object, holder, function, name, check);
+    const int id = function_info->custom_call_generator_id();
+    Object* result =
+        CompileCustomCall(id, object, holder, function, name, check);
     // undefined means bail out to regular compiler.
     if (!result->IsUndefined()) {
       return result;
@@ -1334,11 +1326,7 @@ Object* CallStubCompiler::CompileCallConstant(Object* object,
   __ Jump(ic, RelocInfo::CODE_TARGET);
 
   // Return the generated code.
-  String* function_name = NULL;
-  if (function->shared()->name()->IsString()) {
-    function_name = String::cast(function->shared()->name());
-  }
-  return GetCode(CONSTANT_FUNCTION, function_name);
+  return GetCode(function);
 }
 
 
index ac03c200c20ea05270c7b1e87c2658eeea75cb53..87f363b0c010b1950bfd39f58272cf25ddc34ee9 100644 (file)
@@ -670,16 +670,6 @@ ExternalReference ExternalReference::scheduled_exception_address() {
 }
 
 
-ExternalReference ExternalReference::compile_array_pop_call() {
-  return ExternalReference(FUNCTION_ADDR(CompileArrayPopCall));
-}
-
-
-ExternalReference ExternalReference::compile_array_push_call() {
-  return ExternalReference(FUNCTION_ADDR(CompileArrayPushCall));
-}
-
-
 #ifndef V8_INTERPRETED_REGEXP
 
 ExternalReference ExternalReference::re_check_stack_guard_state() {
index 03a2f8ea1c1a3b01aa5e420a26caf7147cd84d23..5d03c1f854549842fd6f98420a53a2ca71788840 100644 (file)
@@ -444,9 +444,6 @@ class ExternalReference BASE_EMBEDDED {
 
   static ExternalReference scheduled_exception_address();
 
-  static ExternalReference compile_array_pop_call();
-  static ExternalReference compile_array_push_call();
-
   Address address() const {return reinterpret_cast<Address>(address_);}
 
 #ifdef ENABLE_DEBUGGER_SUPPORT
index 657d0dc3dac7acc3ec7084b22c66aafd583569ba..df1e98a66b0ec7c63a5f7ea9ff2f2d42cfbdbd5f 100644 (file)
@@ -37,6 +37,7 @@
 #include "macro-assembler.h"
 #include "natives.h"
 #include "snapshot.h"
+#include "stub-cache.h"
 
 namespace v8 {
 namespace internal {
@@ -228,6 +229,7 @@ class Genesis BASE_EMBEDDED {
   // Used for creating a context from scratch.
   void InstallNativeFunctions();
   bool InstallNatives();
+  void InstallCustomCallGenerators();
   void InstallJSFunctionResultCaches();
   // Used both for deserialized and from-scratch contexts to add the extensions
   // provided.
@@ -1229,6 +1231,8 @@ bool Genesis::InstallNatives() {
 
   InstallNativeFunctions();
 
+  InstallCustomCallGenerators();
+
   // Install Function.prototype.call and apply.
   { Handle<String> key = Factory::function_class_symbol();
     Handle<JSFunction> function =
@@ -1326,6 +1330,29 @@ bool Genesis::InstallNatives() {
 }
 
 
+static void InstallCustomCallGenerator(Handle<JSFunction> holder_function,
+                                       const char* function_name,
+                                       int id) {
+  Handle<JSObject> proto(JSObject::cast(holder_function->instance_prototype()));
+  Handle<String> name = Factory::LookupAsciiSymbol(function_name);
+  Handle<JSFunction> function(JSFunction::cast(proto->GetProperty(*name)));
+  function->shared()->set_function_data(Smi::FromInt(id));
+}
+
+
+void Genesis::InstallCustomCallGenerators() {
+  HandleScope scope;
+#define INSTALL_CALL_GENERATOR(holder_fun, fun_name, name)                \
+  {                                                                       \
+    Handle<JSFunction> holder(global_context()->holder_fun##_function()); \
+    const int id = CallStubCompiler::k##name##CallGenerator;              \
+    InstallCustomCallGenerator(holder, #fun_name, id);                    \
+  }
+  CUSTOM_CALL_IC_GENERATORS(INSTALL_CALL_GENERATOR)
+#undef INSTALL_CALL_GENERATOR
+}
+
+
 // Do not forget to update macros.py with named constant
 // of cache id.
 #define JSFUNCTION_RESULT_CACHE_LIST(F) \
index 809228c7ec5332aa4c863ac405f8e7864f4d25ab..189c0e4d16c668e70e8094ba745c62e3be78a2a8 100644 (file)
@@ -1264,16 +1264,11 @@ Object* CallStubCompiler::CompileArrayPushCall(Object* object,
   }
 
   __ bind(&miss);
-
   Handle<Code> ic = ComputeCallMiss(arguments().immediate());
   __ jmp(ic, RelocInfo::CODE_TARGET);
 
   // Return the generated code.
-  String* function_name = NULL;
-  if (function->shared()->name()->IsString()) {
-    function_name = String::cast(function->shared()->name());
-  }
-  return GetCode(CONSTANT_FUNCTION, function_name);
+  return GetCode(function);
 }
 
 
@@ -1351,16 +1346,11 @@ Object* CallStubCompiler::CompileArrayPopCall(Object* object,
                                1);
 
   __ bind(&miss);
-
   Handle<Code> ic = ComputeCallMiss(arguments().immediate());
   __ jmp(ic, RelocInfo::CODE_TARGET);
 
   // Return the generated code.
-  String* function_name = NULL;
-  if (function->shared()->name()->IsString()) {
-    function_name = String::cast(function->shared()->name());
-  }
-  return GetCode(CONSTANT_FUNCTION, function_name);
+  return GetCode(function);
 }
 
 
@@ -1379,9 +1369,9 @@ Object* CallStubCompiler::CompileCallConstant(Object* object,
 
   SharedFunctionInfo* function_info = function->shared();
   if (function_info->HasCustomCallGenerator()) {
-    CustomCallGenerator generator =
-        ToCData<CustomCallGenerator>(function_info->function_data());
-    Object* result = generator(this, object, holder, function, name, check);
+    const int id = function_info->custom_call_generator_id();
+    Object* result =
+        CompileCustomCall(id, object, holder, function, name, check);
     // undefined means bail out to regular compiler.
     if (!result->IsUndefined()) {
       return result;
@@ -1518,11 +1508,7 @@ Object* CallStubCompiler::CompileCallConstant(Object* object,
   __ jmp(ic, RelocInfo::CODE_TARGET);
 
   // Return the generated code.
-  String* function_name = NULL;
-  if (function->shared()->name()->IsString()) {
-    function_name = String::cast(function->shared()->name());
-  }
-  return GetCode(CONSTANT_FUNCTION, function_name);
+  return GetCode(function);
 }
 
 
index ae7d2c2a97201de87ca7bc89e547462d1f8cf4e3..ad151041528b3a7e4b75146eda063f7f68e09549 100644 (file)
@@ -2530,7 +2530,13 @@ FunctionTemplateInfo* SharedFunctionInfo::get_api_func_data() {
 
 
 bool SharedFunctionInfo::HasCustomCallGenerator() {
-  return function_data()->IsProxy();
+  return function_data()->IsSmi();
+}
+
+
+int SharedFunctionInfo::custom_call_generator_id() {
+  ASSERT(HasCustomCallGenerator());
+  return Smi::cast(function_data())->value();
 }
 
 
index dcfb2eedad09ff06cbcb67bd5da2b65faa0e7183..06b1ca081c3363957a09dacdfa0854b66e17b104 100644 (file)
@@ -3200,7 +3200,7 @@ class SharedFunctionInfo: public HeapObject {
 
   // [function data]: This field holds some additional data for function.
   // Currently it either has FunctionTemplateInfo to make benefit the API
-  // or Proxy wrapping CustomCallGenerator.
+  // or Smi identifying a custom call generator.
   // In the long run we don't want all functions to have this field but
   // we can fix that when we have a better model for storing hidden data
   // on objects.
@@ -3209,6 +3209,7 @@ class SharedFunctionInfo: public HeapObject {
   inline bool IsApiFunction();
   inline FunctionTemplateInfo* get_api_func_data();
   inline bool HasCustomCallGenerator();
+  inline int custom_call_generator_id();
 
   // [script info]: Script from which the function originates.
   DECL_ACCESSORS(script, Object)
index 823889aced4b952183c336d3319fc43e27edf68e..b421ac714766082b7bcbecc7ae473495da6b4e40 100644 (file)
@@ -1325,18 +1325,9 @@ static Object* Runtime_FinishArrayPrototypeSetup(Arguments args) {
 }
 
 
-static void SetCustomCallGenerator(Handle<JSFunction> function,
-                                   ExternalReference* generator) {
-  if (function->shared()->function_data()->IsUndefined()) {
-    function->shared()->set_function_data(*FromCData(generator->address()));
-  }
-}
-
-
 static Handle<JSFunction> InstallBuiltin(Handle<JSObject> holder,
                                          const char* name,
-                                         Builtins::Name builtin_name,
-                                         ExternalReference* generator = NULL) {
+                                         Builtins::Name builtin_name) {
   Handle<String> key = Factory::LookupAsciiSymbol(name);
   Handle<Code> code(Builtins::builtin(builtin_name));
   Handle<JSFunction> optimized = Factory::NewFunction(key,
@@ -1345,44 +1336,18 @@ static Handle<JSFunction> InstallBuiltin(Handle<JSObject> holder,
                                                       code,
                                                       false);
   optimized->shared()->DontAdaptArguments();
-  if (generator != NULL) {
-    SetCustomCallGenerator(optimized, generator);
-  }
   SetProperty(holder, key, optimized, NONE);
   return optimized;
 }
 
 
-Object* CompileArrayPushCall(CallStubCompiler* compiler,
-                             Object* object,
-                             JSObject* holder,
-                             JSFunction* function,
-                             String* name,
-                             StubCompiler::CheckType check) {
-  return compiler->CompileArrayPushCall(object, holder, function, name, check);
-}
-
-
-Object* CompileArrayPopCall(CallStubCompiler* compiler,
-                            Object* object,
-                            JSObject* holder,
-                            JSFunction* function,
-                            String* name,
-                            StubCompiler::CheckType check) {
-  return compiler->CompileArrayPopCall(object, holder, function, name, check);
-}
-
-
 static Object* Runtime_SpecialArrayFunctions(Arguments args) {
   HandleScope scope;
   ASSERT(args.length() == 1);
   CONVERT_ARG_CHECKED(JSObject, holder, 0);
 
-  ExternalReference pop = ExternalReference::compile_array_pop_call();
-  ExternalReference push = ExternalReference::compile_array_push_call();
-
-  InstallBuiltin(holder, "pop", Builtins::ArrayPop, &pop);
-  InstallBuiltin(holder, "push", Builtins::ArrayPush, &push);
+  InstallBuiltin(holder, "pop", Builtins::ArrayPop);
+  InstallBuiltin(holder, "push", Builtins::ArrayPush);
   InstallBuiltin(holder, "shift", Builtins::ArrayShift);
   InstallBuiltin(holder, "unshift", Builtins::ArrayUnshift);
   InstallBuiltin(holder, "slice", Builtins::ArraySlice);
index 68412677f49bb0c76a25f2a1bd337c59ef7c1159..dcaa1011555b203d632066c9235fce7068e605d2 100644 (file)
@@ -414,44 +414,36 @@ void ExternalReferenceTable::PopulateTable() {
       UNCLASSIFIED,
       19,
       "compare_doubles");
-  Add(ExternalReference::compile_array_pop_call().address(),
-      UNCLASSIFIED,
-      20,
-      "compile_array_pop");
-  Add(ExternalReference::compile_array_push_call().address(),
-      UNCLASSIFIED,
-      21,
-      "compile_array_push");
 #ifndef V8_INTERPRETED_REGEXP
   Add(ExternalReference::re_case_insensitive_compare_uc16().address(),
       UNCLASSIFIED,
-      22,
+      20,
       "NativeRegExpMacroAssembler::CaseInsensitiveCompareUC16()");
   Add(ExternalReference::re_check_stack_guard_state().address(),
       UNCLASSIFIED,
-      23,
+      21,
       "RegExpMacroAssembler*::CheckStackGuardState()");
   Add(ExternalReference::re_grow_stack().address(),
       UNCLASSIFIED,
-      24,
+      22,
       "NativeRegExpMacroAssembler::GrowStack()");
   Add(ExternalReference::re_word_character_map().address(),
       UNCLASSIFIED,
-      25,
+      23,
       "NativeRegExpMacroAssembler::word_character_map");
 #endif  // V8_INTERPRETED_REGEXP
   // Keyed lookup cache.
   Add(ExternalReference::keyed_lookup_cache_keys().address(),
       UNCLASSIFIED,
-      26,
+      24,
       "KeyedLookupCache::keys()");
   Add(ExternalReference::keyed_lookup_cache_field_offsets().address(),
       UNCLASSIFIED,
-      27,
+      25,
       "KeyedLookupCache::field_offsets()");
   Add(ExternalReference::transcendental_cache_array_address().address(),
       UNCLASSIFIED,
-      28,
+      26,
       "TranscendentalCache::caches()");
 }
 
index f3532533e7e01ac09996b96543dd10e40969d45d..6ebe495f16830b276ba0a115a1d1efe69a5ee018 100644 (file)
@@ -1142,6 +1142,29 @@ Object* KeyedStoreStubCompiler::GetCode(PropertyType type, String* name) {
 }
 
 
+Object* CallStubCompiler::CompileCustomCall(int generator_id,
+                                            Object* object,
+                                            JSObject* holder,
+                                            JSFunction* function,
+                                            String* fname,
+                                            CheckType check) {
+    ASSERT(generator_id >= 0 && generator_id < kNumCallGenerators);
+    switch (generator_id) {
+#define CALL_GENERATOR_CASE(ignored1, ignored2, name)          \
+      case k##name##CallGenerator:                             \
+        return CallStubCompiler::Compile##name##Call(object,   \
+                                                     holder,   \
+                                                     function, \
+                                                     fname,    \
+                                                     check);
+      CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE)
+#undef CALL_GENERATOR_CASE
+    }
+    UNREACHABLE();
+    return Heap::undefined_value();
+}
+
+
 Object* CallStubCompiler::GetCode(PropertyType type, String* name) {
   int argc = arguments_.immediate();
   Code::Flags flags = Code::ComputeMonomorphicFlags(Code::CALL_IC,
@@ -1152,6 +1175,15 @@ Object* CallStubCompiler::GetCode(PropertyType type, String* name) {
 }
 
 
+Object* CallStubCompiler::GetCode(JSFunction* function) {
+  String* function_name = NULL;
+  if (function->shared()->name()->IsString()) {
+    function_name = String::cast(function->shared()->name());
+  }
+  return GetCode(CONSTANT_FUNCTION, function_name);
+}
+
+
 Object* ConstructStubCompiler::GetCode() {
   Code::Flags flags = Code::ComputeFlags(Code::STUB);
   Object* result = GetCodeWithFlags(flags, "ConstructStub");
index 2e0faf6a897b2fee0f8401e0300dd1f23c178012..45aaf75c91796a35ad6fbb29330eed2df088e5c2 100644 (file)
@@ -559,8 +559,30 @@ class KeyedStoreStubCompiler: public StubCompiler {
 };
 
 
+// List of functions with custom constant call IC stubs.
+//
+// Installation of custom call generators for the selected builtins is
+// handled by the bootstrapper.
+//
+// Each entry has a name of a global function (lowercased), a name of
+// a builtin function on its instance prototype (the one the generator
+// is set for), and a name of a generator itself (used to build ids
+// and generator function names).
+#define CUSTOM_CALL_IC_GENERATORS(V) \
+  V(array, push, ArrayPush) \
+  V(array, pop, ArrayPop)
+
+
 class CallStubCompiler: public StubCompiler {
  public:
+  enum {
+#define DECLARE_CALL_GENERATOR_ID(ignored1, ignored2, name) \
+    k##name##CallGenerator,
+    CUSTOM_CALL_IC_GENERATORS(DECLARE_CALL_GENERATOR_ID)
+#undef DECLARE_CALL_GENERATOR_ID
+    kNumCallGenerators
+  };
+
   CallStubCompiler(int argc, InLoopFlag in_loop)
       : arguments_(argc), in_loop_(in_loop) { }
 
@@ -582,17 +604,22 @@ class CallStubCompiler: public StubCompiler {
                             JSFunction* function,
                             String* name);
 
-  Object* CompileArrayPushCall(Object* object,
-                               JSObject* holder,
-                               JSFunction* function,
-                               String* name,
-                               CheckType check);
+  // Compiles a custom call constant IC using the generator with given id.
+  Object* CompileCustomCall(int generator_id,
+                            Object* object,
+                            JSObject* holder,
+                            JSFunction* function,
+                            String* name,
+                            CheckType check);
 
-  Object* CompileArrayPopCall(Object* object,
-                              JSObject* holder,
-                              JSFunction* function,
-                              String* name,
+#define DECLARE_CALL_GENERATOR(ignored1, ignored2, name) \
+  Object* Compile##name##Call(Object* object,            \
+                              JSObject* holder,          \
+                              JSFunction* function,      \
+                              String* fname,             \
                               CheckType check);
+  CUSTOM_CALL_IC_GENERATORS(DECLARE_CALL_GENERATOR)
+#undef DECLARE_CALL_GENERATOR
 
  private:
   const ParameterCount arguments_;
@@ -601,6 +628,10 @@ class CallStubCompiler: public StubCompiler {
   const ParameterCount& arguments() { return arguments_; }
 
   Object* GetCode(PropertyType type, String* name);
+
+  // Convenience function. Calls GetCode above passing
+  // CONSTANT_FUNCTION type and the name of the given function.
+  Object* GetCode(JSFunction* function);
 };
 
 
@@ -663,31 +694,6 @@ class CallOptimization BASE_EMBEDDED {
   CallHandlerInfo* api_call_info_;
 };
 
-
-typedef Object* (*CustomCallGenerator)(CallStubCompiler* compiler,
-                                       Object* object,
-                                       JSObject* holder,
-                                       JSFunction* function,
-                                       String* name,
-                                       StubCompiler::CheckType check);
-
-
-Object* CompileArrayPushCall(CallStubCompiler* compiler,
-                             Object* object,
-                             JSObject* holder,
-                             JSFunction* function,
-                             String* name,
-                             StubCompiler::CheckType check);
-
-
-Object* CompileArrayPopCall(CallStubCompiler* compiler,
-                            Object* object,
-                            JSObject* holder,
-                            JSFunction* function,
-                            String* name,
-                            StubCompiler::CheckType check);
-
-
 } }  // namespace v8::internal
 
 #endif  // V8_STUB_CACHE_H_
index 7d4410cb00fe28391ee6b95b2be091eef2330a4c..dbe1c28e4fe81e9dde0eb358af0f5708927926e0 100644 (file)
@@ -870,9 +870,9 @@ Object* CallStubCompiler::CompileCallConstant(Object* object,
 
   SharedFunctionInfo* function_info = function->shared();
   if (function_info->HasCustomCallGenerator()) {
-    CustomCallGenerator generator =
-        ToCData<CustomCallGenerator>(function_info->function_data());
-    Object* result = generator(this, object, holder, function, name, check);
+    const int id = function_info->custom_call_generator_id();
+    Object* result =
+        CompileCustomCall(id, object, holder, function, name, check);
     // undefined means bail out to regular compiler.
     if (!result->IsUndefined()) {
       return result;
@@ -1007,11 +1007,7 @@ Object* CallStubCompiler::CompileCallConstant(Object* object,
   __ Jump(ic, RelocInfo::CODE_TARGET);
 
   // Return the generated code.
-  String* function_name = NULL;
-  if (function->shared()->name()->IsString()) {
-    function_name = String::cast(function->shared()->name());
-  }
-  return GetCode(CONSTANT_FUNCTION, function_name);
+  return GetCode(function);
 }
 
 
@@ -1219,11 +1215,7 @@ Object* CallStubCompiler::CompileArrayPushCall(Object* object,
   __ jmp(ic, RelocInfo::CODE_TARGET);
 
   // Return the generated code.
-  String* function_name = NULL;
-  if (function->shared()->name()->IsString()) {
-    function_name = String::cast(function->shared()->name());
-  }
-  return GetCode(CONSTANT_FUNCTION, function_name);
+  return GetCode(function);
 }
 
 
@@ -1308,11 +1300,7 @@ Object* CallStubCompiler::CompileArrayPopCall(Object* object,
   __ jmp(ic, RelocInfo::CODE_TARGET);
 
   // Return the generated code.
-  String* function_name = NULL;
-  if (function->shared()->name()->IsString()) {
-    function_name = String::cast(function->shared()->name());
-  }
-  return GetCode(CONSTANT_FUNCTION, function_name);
+  return GetCode(function);
 }