Move PropertyAccessCompiler and CallOptimization to their own files
authorverwaest@chromium.org <verwaest@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 22 Aug 2014 14:36:54 +0000 (14:36 +0000)
committerverwaest@chromium.org <verwaest@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 22 Aug 2014 14:36:54 +0000 (14:36 +0000)
BUG=
R=yangguo@chromium.org

Review URL: https://codereview.chromium.org/480413008

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

18 files changed:
BUILD.gn
src/hydrogen.cc
src/ic/access-compiler.cc [new file with mode: 0644]
src/ic/access-compiler.h [new file with mode: 0644]
src/ic/arm/access-compiler-arm.cc [new file with mode: 0644]
src/ic/arm/ic-compiler-arm.cc
src/ic/arm64/access-compiler-arm64.cc [new file with mode: 0644]
src/ic/arm64/ic-compiler-arm64.cc
src/ic/call-optimization.cc [new file with mode: 0644]
src/ic/call-optimization.h [new file with mode: 0644]
src/ic/ia32/access-compiler-ia32.cc [new file with mode: 0644]
src/ic/ia32/ic-compiler-ia32.cc
src/ic/ic-compiler.cc
src/ic/ic-compiler.h
src/ic/ic.cc
src/ic/x64/access-compiler-x64.cc [new file with mode: 0644]
src/ic/x64/ic-compiler-x64.cc
tools/gyp/v8.gyp

index 79dcecf10e5a9ddc9165f6fc03b8207768b7cad1..8512dea86ba6294447de064da041eb0ca6cebb2c 100644 (file)
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -714,6 +714,10 @@ source_set("v8_base") {
     "src/i18n.h",
     "src/icu_util.cc",
     "src/icu_util.h",
+    "src/ic/access-compiler.cc",
+    "src/ic/access-compiler.h",
+    "src/ic/call-optimization.cc",
+    "src/ic/call-optimization.h",
     "src/ic/ic-inl.h",
     "src/ic/ic.cc",
     "src/ic/ic.h",
@@ -929,6 +933,7 @@ source_set("v8_base") {
       "src/compiler/x64/instruction-codes-x64.h",
       "src/compiler/x64/instruction-selector-x64.cc",
       "src/compiler/x64/linkage-x64.cc",
+      "src/ic/x64/access-compiler-x64.cc",
       "src/ic/x64/ic-x64.cc",
       "src/ic/x64/ic-compiler-x64.cc",
       "src/ic/x64/stub-cache-x64.cc",
@@ -967,6 +972,7 @@ source_set("v8_base") {
       "src/compiler/arm/instruction-codes-arm.h",
       "src/compiler/arm/instruction-selector-arm.cc",
       "src/compiler/arm/linkage-arm.cc",
+      "src/ic/arm/access-compiler-arm.cc",
       "src/ic/arm/ic-arm.cc",
       "src/ic/arm/ic-compiler-arm.cc",
       "src/ic/arm/stub-cache-arm.cc",
@@ -1016,6 +1022,7 @@ source_set("v8_base") {
       "src/compiler/arm64/instruction-codes-arm64.h",
       "src/compiler/arm64/instruction-selector-arm64.cc",
       "src/compiler/arm64/linkage-arm64.cc",
+      "src/ic/arm64/access-compiler-arm64.cc",
       "src/ic/arm64/ic-arm64.cc",
       "src/ic/arm64/ic-compiler-arm64.cc",
       "src/ic/arm64/stub-cache-arm64.cc",
index bd646f1976882b4a0565a72016c004880d5c1e18..1ad5d95bf61ca4328f03cd10ab6cceb54bd060a6 100644 (file)
 #include "src/hydrogen-sce.h"
 #include "src/hydrogen-store-elimination.h"
 #include "src/hydrogen-uint32-analysis.h"
+#include "src/ic/call-optimization.h"
+// GetRootConstructor
+#include "src/ic/ic-inl.h"
 #include "src/lithium-allocator.h"
 #include "src/parser.h"
 #include "src/runtime.h"
 #include "src/scopeinfo.h"
 #include "src/scopes.h"
 #include "src/typing.h"
-// CallOptimization
-#include "src/ic/ic-compiler.h"
-// GetRootConstructor
-#include "src/ic/ic-inl.h"
 
 #if V8_TARGET_ARCH_IA32
 #include "src/ia32/lithium-codegen-ia32.h"  // NOLINT
diff --git a/src/ic/access-compiler.cc b/src/ic/access-compiler.cc
new file mode 100644 (file)
index 0000000..c3bf11c
--- /dev/null
@@ -0,0 +1,55 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/v8.h"
+
+#include "src/ic/access-compiler.h"
+
+
+namespace v8 {
+namespace internal {
+
+
+Handle<Code> PropertyAccessCompiler::GetCodeWithFlags(Code::Flags flags,
+                                                      const char* name) {
+  // Create code object in the heap.
+  CodeDesc desc;
+  masm()->GetCode(&desc);
+  Handle<Code> code = factory()->NewCode(desc, flags, masm()->CodeObject());
+  if (code->IsCodeStubOrIC()) code->set_stub_key(CodeStub::NoCacheKey());
+#ifdef ENABLE_DISASSEMBLER
+  if (FLAG_print_code_stubs) {
+    OFStream os(stdout);
+    code->Disassemble(name, os);
+  }
+#endif
+  return code;
+}
+
+
+Handle<Code> PropertyAccessCompiler::GetCodeWithFlags(Code::Flags flags,
+                                                      Handle<Name> name) {
+  return (FLAG_print_code_stubs && !name.is_null() && name->IsString())
+             ? GetCodeWithFlags(flags,
+                                Handle<String>::cast(name)->ToCString().get())
+             : GetCodeWithFlags(flags, NULL);
+}
+
+
+void PropertyAccessCompiler::TailCallBuiltin(MacroAssembler* masm,
+                                             Builtins::Name name) {
+  Handle<Code> code(masm->isolate()->builtins()->builtin(name));
+  GenerateTailCall(masm, code);
+}
+
+
+Register* PropertyAccessCompiler::GetCallingConvention(Code::Kind kind) {
+  if (kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC) {
+    return load_calling_convention();
+  }
+  DCHECK(kind == Code::STORE_IC || kind == Code::KEYED_STORE_IC);
+  return store_calling_convention();
+}
+}
+}  // namespace v8::internal
diff --git a/src/ic/access-compiler.h b/src/ic/access-compiler.h
new file mode 100644 (file)
index 0000000..928b70b
--- /dev/null
@@ -0,0 +1,83 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8_IC_ACCESS_COMPILER_H_
+#define V8_IC_ACCESS_COMPILER_H_
+
+#include "src/code-stubs.h"
+#include "src/macro-assembler.h"
+#include "src/objects.h"
+
+namespace v8 {
+namespace internal {
+
+
+class PropertyAccessCompiler BASE_EMBEDDED {
+ public:
+  static Builtins::Name MissBuiltin(Code::Kind kind) {
+    switch (kind) {
+      case Code::LOAD_IC:
+        return Builtins::kLoadIC_Miss;
+      case Code::STORE_IC:
+        return Builtins::kStoreIC_Miss;
+      case Code::KEYED_LOAD_IC:
+        return Builtins::kKeyedLoadIC_Miss;
+      case Code::KEYED_STORE_IC:
+        return Builtins::kKeyedStoreIC_Miss;
+      default:
+        UNREACHABLE();
+    }
+    return Builtins::kLoadIC_Miss;
+  }
+
+  static void TailCallBuiltin(MacroAssembler* masm, Builtins::Name name);
+
+ protected:
+  PropertyAccessCompiler(Isolate* isolate, Code::Kind kind,
+                         CacheHolderFlag cache_holder)
+      : registers_(GetCallingConvention(kind)),
+        kind_(kind),
+        cache_holder_(cache_holder),
+        isolate_(isolate),
+        masm_(isolate, NULL, 256) {}
+
+  Code::Kind kind() const { return kind_; }
+  CacheHolderFlag cache_holder() const { return cache_holder_; }
+  MacroAssembler* masm() { return &masm_; }
+  Isolate* isolate() const { return isolate_; }
+  Heap* heap() const { return isolate()->heap(); }
+  Factory* factory() const { return isolate()->factory(); }
+
+  Register receiver() const { return registers_[0]; }
+  Register name() const { return registers_[1]; }
+  Register scratch1() const { return registers_[2]; }
+  Register scratch2() const { return registers_[3]; }
+  Register scratch3() const { return registers_[4]; }
+
+  // Calling convention between indexed store IC and handler.
+  Register transition_map() const { return scratch1(); }
+
+  static Register* GetCallingConvention(Code::Kind);
+  static Register* load_calling_convention();
+  static Register* store_calling_convention();
+  static Register* keyed_store_calling_convention();
+
+  Register* registers_;
+
+  static void GenerateTailCall(MacroAssembler* masm, Handle<Code> code);
+
+  Handle<Code> GetCodeWithFlags(Code::Flags flags, const char* name);
+  Handle<Code> GetCodeWithFlags(Code::Flags flags, Handle<Name> name);
+
+ private:
+  Code::Kind kind_;
+  CacheHolderFlag cache_holder_;
+
+  Isolate* isolate_;
+  MacroAssembler masm_;
+};
+}
+}  // namespace v8::internal
+
+#endif  // V8_IC_ACCESS_COMPILER_H_
diff --git a/src/ic/arm/access-compiler-arm.cc b/src/ic/arm/access-compiler-arm.cc
new file mode 100644 (file)
index 0000000..2a95157
--- /dev/null
@@ -0,0 +1,46 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/v8.h"
+
+#if V8_TARGET_ARCH_ARM
+
+#include "src/ic/access-compiler.h"
+
+namespace v8 {
+namespace internal {
+
+#define __ ACCESS_MASM(masm)
+
+
+void PropertyAccessCompiler::GenerateTailCall(MacroAssembler* masm,
+                                              Handle<Code> code) {
+  __ Jump(code, RelocInfo::CODE_TARGET);
+}
+
+
+Register* PropertyAccessCompiler::load_calling_convention() {
+  // receiver, name, scratch1, scratch2, scratch3, scratch4.
+  Register receiver = LoadIC::ReceiverRegister();
+  Register name = LoadIC::NameRegister();
+  static Register registers[] = {receiver, name, r3, r0, r4, r5};
+  return registers;
+}
+
+
+Register* PropertyAccessCompiler::store_calling_convention() {
+  // receiver, name, scratch1, scratch2, scratch3.
+  Register receiver = StoreIC::ReceiverRegister();
+  Register name = StoreIC::NameRegister();
+  DCHECK(r3.is(KeyedStoreIC::MapRegister()));
+  static Register registers[] = {receiver, name, r3, r4, r5};
+  return registers;
+}
+
+
+#undef __
+}
+}  // namespace v8::internal
+
+#endif  // V8_TARGET_ARCH_IA32
index ac0da716ee67bfe9b85b9be57991bcfde48747d2..c5b0903b9e76fa7a9f1e4803d4465f50f1ee6f10 100644 (file)
@@ -6,6 +6,7 @@
 
 #if V8_TARGET_ARCH_ARM
 
+#include "src/ic/call-optimization.h"
 #include "src/ic/ic-compiler.h"
 
 namespace v8 {
@@ -209,12 +210,6 @@ void PropertyHandlerCompiler::GenerateFastApiCall(
 }
 
 
-void PropertyAccessCompiler::GenerateTailCall(MacroAssembler* masm,
-                                              Handle<Code> code) {
-  __ Jump(code, RelocInfo::CODE_TARGET);
-}
-
-
 #undef __
 #define __ ACCESS_MASM(masm())
 
@@ -751,25 +746,6 @@ Handle<Code> NamedStoreHandlerCompiler::CompileStoreInterceptor(
 }
 
 
-Register* PropertyAccessCompiler::load_calling_convention() {
-  // receiver, name, scratch1, scratch2, scratch3, scratch4.
-  Register receiver = LoadIC::ReceiverRegister();
-  Register name = LoadIC::NameRegister();
-  static Register registers[] = {receiver, name, r3, r0, r4, r5};
-  return registers;
-}
-
-
-Register* PropertyAccessCompiler::store_calling_convention() {
-  // receiver, name, scratch1, scratch2, scratch3.
-  Register receiver = StoreIC::ReceiverRegister();
-  Register name = StoreIC::NameRegister();
-  DCHECK(r3.is(KeyedStoreIC::MapRegister()));
-  static Register registers[] = {receiver, name, r3, r4, r5};
-  return registers;
-}
-
-
 Register NamedStoreHandlerCompiler::value() { return StoreIC::ValueRegister(); }
 
 
diff --git a/src/ic/arm64/access-compiler-arm64.cc b/src/ic/arm64/access-compiler-arm64.cc
new file mode 100644 (file)
index 0000000..c1659ae
--- /dev/null
@@ -0,0 +1,53 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/v8.h"
+
+#if V8_TARGET_ARCH_ARM64
+
+#include "src/ic/access-compiler.h"
+
+namespace v8 {
+namespace internal {
+
+#define __ ACCESS_MASM(masm)
+
+
+void PropertyAccessCompiler::GenerateTailCall(MacroAssembler* masm,
+                                              Handle<Code> code) {
+  __ Jump(code, RelocInfo::CODE_TARGET);
+}
+
+
+// TODO(all): The so-called scratch registers are significant in some cases. For
+// example, PropertyAccessCompiler::keyed_store_calling_convention()[3] (x3) is
+// actually
+// used for KeyedStoreCompiler::transition_map(). We should verify which
+// registers are actually scratch registers, and which are important. For now,
+// we use the same assignments as ARM to remain on the safe side.
+
+Register* PropertyAccessCompiler::load_calling_convention() {
+  // receiver, name, scratch1, scratch2, scratch3, scratch4.
+  Register receiver = LoadIC::ReceiverRegister();
+  Register name = LoadIC::NameRegister();
+  static Register registers[] = {receiver, name, x3, x0, x4, x5};
+  return registers;
+}
+
+
+Register* PropertyAccessCompiler::store_calling_convention() {
+  // receiver, value, scratch1, scratch2, scratch3.
+  Register receiver = StoreIC::ReceiverRegister();
+  Register name = StoreIC::NameRegister();
+  DCHECK(x3.is(KeyedStoreIC::MapRegister()));
+  static Register registers[] = {receiver, name, x3, x4, x5};
+  return registers;
+}
+
+
+#undef __
+}
+}  // namespace v8::internal
+
+#endif  // V8_TARGET_ARCH_ARM64
index d15a07d64b3e9c7804bad78281371a10c39363e4..3e7f8f50a0a39c8d00819b70d103f7d1a7605aa1 100644 (file)
@@ -6,6 +6,7 @@
 
 #if V8_TARGET_ARCH_ARM64
 
+#include "src/ic/call-optimization.h"
 #include "src/ic/ic-compiler.h"
 
 namespace v8 {
@@ -205,12 +206,6 @@ void PropertyHandlerCompiler::GenerateFastApiCall(
 }
 
 
-void PropertyAccessCompiler::GenerateTailCall(MacroAssembler* masm,
-                                              Handle<Code> code) {
-  __ Jump(code, RelocInfo::CODE_TARGET);
-}
-
-
 #undef __
 #define __ ACCESS_MASM(masm())
 
@@ -763,32 +758,6 @@ Handle<Code> NamedStoreHandlerCompiler::CompileStoreInterceptor(
 }
 
 
-// TODO(all): The so-called scratch registers are significant in some cases. For
-// example, PropertyAccessCompiler::keyed_store_calling_convention()[3] (x3) is
-// actually
-// used for KeyedStoreCompiler::transition_map(). We should verify which
-// registers are actually scratch registers, and which are important. For now,
-// we use the same assignments as ARM to remain on the safe side.
-
-Register* PropertyAccessCompiler::load_calling_convention() {
-  // receiver, name, scratch1, scratch2, scratch3, scratch4.
-  Register receiver = LoadIC::ReceiverRegister();
-  Register name = LoadIC::NameRegister();
-  static Register registers[] = {receiver, name, x3, x0, x4, x5};
-  return registers;
-}
-
-
-Register* PropertyAccessCompiler::store_calling_convention() {
-  // receiver, value, scratch1, scratch2, scratch3.
-  Register receiver = StoreIC::ReceiverRegister();
-  Register name = StoreIC::NameRegister();
-  DCHECK(x3.is(KeyedStoreIC::MapRegister()));
-  static Register registers[] = {receiver, name, x3, x4, x5};
-  return registers;
-}
-
-
 Register NamedStoreHandlerCompiler::value() { return StoreIC::ValueRegister(); }
 
 
diff --git a/src/ic/call-optimization.cc b/src/ic/call-optimization.cc
new file mode 100644 (file)
index 0000000..7ef1b7e
--- /dev/null
@@ -0,0 +1,113 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/v8.h"
+
+#include "src/ic/call-optimization.h"
+
+
+namespace v8 {
+namespace internal {
+
+CallOptimization::CallOptimization(Handle<JSFunction> function) {
+  Initialize(function);
+}
+
+
+Handle<JSObject> CallOptimization::LookupHolderOfExpectedType(
+    Handle<Map> object_map, HolderLookup* holder_lookup) const {
+  DCHECK(is_simple_api_call());
+  if (!object_map->IsJSObjectMap()) {
+    *holder_lookup = kHolderNotFound;
+    return Handle<JSObject>::null();
+  }
+  if (expected_receiver_type_.is_null() ||
+      expected_receiver_type_->IsTemplateFor(*object_map)) {
+    *holder_lookup = kHolderIsReceiver;
+    return Handle<JSObject>::null();
+  }
+  while (true) {
+    if (!object_map->prototype()->IsJSObject()) break;
+    Handle<JSObject> prototype(JSObject::cast(object_map->prototype()));
+    if (!prototype->map()->is_hidden_prototype()) break;
+    object_map = handle(prototype->map());
+    if (expected_receiver_type_->IsTemplateFor(*object_map)) {
+      *holder_lookup = kHolderFound;
+      return prototype;
+    }
+  }
+  *holder_lookup = kHolderNotFound;
+  return Handle<JSObject>::null();
+}
+
+
+bool CallOptimization::IsCompatibleReceiver(Handle<Object> receiver,
+                                            Handle<JSObject> holder) const {
+  DCHECK(is_simple_api_call());
+  if (!receiver->IsJSObject()) return false;
+  Handle<Map> map(JSObject::cast(*receiver)->map());
+  HolderLookup holder_lookup;
+  Handle<JSObject> api_holder = LookupHolderOfExpectedType(map, &holder_lookup);
+  switch (holder_lookup) {
+    case kHolderNotFound:
+      return false;
+    case kHolderIsReceiver:
+      return true;
+    case kHolderFound:
+      if (api_holder.is_identical_to(holder)) return true;
+      // Check if holder is in prototype chain of api_holder.
+      {
+        JSObject* object = *api_holder;
+        while (true) {
+          Object* prototype = object->map()->prototype();
+          if (!prototype->IsJSObject()) return false;
+          if (prototype == *holder) return true;
+          object = JSObject::cast(prototype);
+        }
+      }
+      break;
+  }
+  UNREACHABLE();
+  return false;
+}
+
+
+void CallOptimization::Initialize(Handle<JSFunction> function) {
+  constant_function_ = Handle<JSFunction>::null();
+  is_simple_api_call_ = false;
+  expected_receiver_type_ = Handle<FunctionTemplateInfo>::null();
+  api_call_info_ = Handle<CallHandlerInfo>::null();
+
+  if (function.is_null() || !function->is_compiled()) return;
+
+  constant_function_ = function;
+  AnalyzePossibleApiFunction(function);
+}
+
+
+void CallOptimization::AnalyzePossibleApiFunction(Handle<JSFunction> function) {
+  if (!function->shared()->IsApiFunction()) return;
+  Handle<FunctionTemplateInfo> info(function->shared()->get_api_func_data());
+
+  // Require a C++ callback.
+  if (info->call_code()->IsUndefined()) return;
+  api_call_info_ =
+      Handle<CallHandlerInfo>(CallHandlerInfo::cast(info->call_code()));
+
+  // Accept signatures that either have no restrictions at all or
+  // only have restrictions on the receiver.
+  if (!info->signature()->IsUndefined()) {
+    Handle<SignatureInfo> signature =
+        Handle<SignatureInfo>(SignatureInfo::cast(info->signature()));
+    if (!signature->args()->IsUndefined()) return;
+    if (!signature->receiver()->IsUndefined()) {
+      expected_receiver_type_ = Handle<FunctionTemplateInfo>(
+          FunctionTemplateInfo::cast(signature->receiver()));
+    }
+  }
+
+  is_simple_api_call_ = true;
+}
+}
+}  // namespace v8::internal
diff --git a/src/ic/call-optimization.h b/src/ic/call-optimization.h
new file mode 100644 (file)
index 0000000..99494fa
--- /dev/null
@@ -0,0 +1,62 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8_IC_CALL_OPTIMIZATION_H_
+#define V8_IC_CALL_OPTIMIZATION_H_
+
+#include "src/code-stubs.h"
+#include "src/ic/access-compiler.h"
+#include "src/macro-assembler.h"
+#include "src/objects.h"
+
+namespace v8 {
+namespace internal {
+// Holds information about possible function call optimizations.
+class CallOptimization BASE_EMBEDDED {
+ public:
+  explicit CallOptimization(Handle<JSFunction> function);
+
+  bool is_constant_call() const { return !constant_function_.is_null(); }
+
+  Handle<JSFunction> constant_function() const {
+    DCHECK(is_constant_call());
+    return constant_function_;
+  }
+
+  bool is_simple_api_call() const { return is_simple_api_call_; }
+
+  Handle<FunctionTemplateInfo> expected_receiver_type() const {
+    DCHECK(is_simple_api_call());
+    return expected_receiver_type_;
+  }
+
+  Handle<CallHandlerInfo> api_call_info() const {
+    DCHECK(is_simple_api_call());
+    return api_call_info_;
+  }
+
+  enum HolderLookup { kHolderNotFound, kHolderIsReceiver, kHolderFound };
+  Handle<JSObject> LookupHolderOfExpectedType(
+      Handle<Map> receiver_map, HolderLookup* holder_lookup) const;
+
+  // Check if the api holder is between the receiver and the holder.
+  bool IsCompatibleReceiver(Handle<Object> receiver,
+                            Handle<JSObject> holder) const;
+
+ private:
+  void Initialize(Handle<JSFunction> function);
+
+  // Determines whether the given function can be called using the
+  // fast api call builtin.
+  void AnalyzePossibleApiFunction(Handle<JSFunction> function);
+
+  Handle<JSFunction> constant_function_;
+  bool is_simple_api_call_;
+  Handle<FunctionTemplateInfo> expected_receiver_type_;
+  Handle<CallHandlerInfo> api_call_info_;
+};
+}
+}  // namespace v8::internal
+
+#endif  // V8_IC_CALL_OPTIMIZATION_H_
diff --git a/src/ic/ia32/access-compiler-ia32.cc b/src/ic/ia32/access-compiler-ia32.cc
new file mode 100644 (file)
index 0000000..0604066
--- /dev/null
@@ -0,0 +1,44 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/v8.h"
+
+#if V8_TARGET_ARCH_IA32
+
+#include "src/ic/access-compiler.h"
+
+namespace v8 {
+namespace internal {
+
+#define __ ACCESS_MASM(masm)
+
+void PropertyAccessCompiler::GenerateTailCall(MacroAssembler* masm,
+                                              Handle<Code> code) {
+  __ jmp(code, RelocInfo::CODE_TARGET);
+}
+
+
+Register* PropertyAccessCompiler::load_calling_convention() {
+  // receiver, name, scratch1, scratch2, scratch3, scratch4.
+  Register receiver = LoadIC::ReceiverRegister();
+  Register name = LoadIC::NameRegister();
+  static Register registers[] = {receiver, name, ebx, eax, edi, no_reg};
+  return registers;
+}
+
+
+Register* PropertyAccessCompiler::store_calling_convention() {
+  // receiver, name, scratch1, scratch2, scratch3.
+  Register receiver = StoreIC::ReceiverRegister();
+  Register name = StoreIC::NameRegister();
+  DCHECK(ebx.is(KeyedStoreIC::MapRegister()));
+  static Register registers[] = {receiver, name, ebx, edi, no_reg};
+  return registers;
+}
+
+#undef __
+}
+}  // namespace v8::internal
+
+#endif  // V8_TARGET_ARCH_IA32
index 7ed1f8d07e11bf2cb6fa2bfefd1d95d88eafb43f..fb1542dfc11fcbe10d2d12e90dd7e2b4f1a29445 100644 (file)
@@ -6,6 +6,7 @@
 
 #if V8_TARGET_ARCH_IA32
 
+#include "src/ic/call-optimization.h"
 #include "src/ic/ic-compiler.h"
 
 namespace v8 {
@@ -206,12 +207,6 @@ void PropertyHandlerCompiler::GenerateCheckPropertyCell(
 }
 
 
-void PropertyAccessCompiler::GenerateTailCall(MacroAssembler* masm,
-                                              Handle<Code> code) {
-  __ jmp(code, RelocInfo::CODE_TARGET);
-}
-
-
 #undef __
 #define __ ACCESS_MASM(masm())
 
@@ -778,25 +773,6 @@ Handle<Code> PropertyICCompiler::CompileKeyedStorePolymorphic(
 }
 
 
-Register* PropertyAccessCompiler::load_calling_convention() {
-  // receiver, name, scratch1, scratch2, scratch3, scratch4.
-  Register receiver = LoadIC::ReceiverRegister();
-  Register name = LoadIC::NameRegister();
-  static Register registers[] = {receiver, name, ebx, eax, edi, no_reg};
-  return registers;
-}
-
-
-Register* PropertyAccessCompiler::store_calling_convention() {
-  // receiver, name, scratch1, scratch2, scratch3.
-  Register receiver = StoreIC::ReceiverRegister();
-  Register name = StoreIC::NameRegister();
-  DCHECK(ebx.is(KeyedStoreIC::MapRegister()));
-  static Register registers[] = {receiver, name, ebx, edi, no_reg};
-  return registers;
-}
-
-
 Register NamedStoreHandlerCompiler::value() { return StoreIC::ValueRegister(); }
 
 
index f31a5c1ac3ebc9a0b46a85e46a7f6e96e752ca22..f555517a2443e989eb3f4ab5b8f52afcf8059a97 100644 (file)
@@ -4,6 +4,7 @@
 
 #include "src/v8.h"
 
+#include "src/ic/call-optimization.h"
 #include "src/ic/ic-inl.h"
 #include "src/ic/ic-compiler.h"
 
@@ -178,9 +179,6 @@ Handle<Code> PropertyICCompiler::ComputeKeyedStoreMonomorphic(
 }
 
 
-#define CALL_LOGGER_TAG(kind, type) (Logger::KEYED_##type)
-
-
 Code* PropertyICCompiler::FindPreMonomorphic(Isolate* isolate, Code::Kind kind,
                                              ExtraICState state) {
   Code::Flags flags = Code::ComputeFlags(kind, PREMONOMORPHIC, state);
@@ -402,35 +400,6 @@ Handle<Code> PropertyICCompiler::CompileStoreMegamorphic(Code::Flags flags) {
 }
 
 
-#undef CALL_LOGGER_TAG
-
-
-Handle<Code> PropertyAccessCompiler::GetCodeWithFlags(Code::Flags flags,
-                                                      const char* name) {
-  // Create code object in the heap.
-  CodeDesc desc;
-  masm()->GetCode(&desc);
-  Handle<Code> code = factory()->NewCode(desc, flags, masm()->CodeObject());
-  if (code->IsCodeStubOrIC()) code->set_stub_key(CodeStub::NoCacheKey());
-#ifdef ENABLE_DISASSEMBLER
-  if (FLAG_print_code_stubs) {
-    OFStream os(stdout);
-    code->Disassemble(name, os);
-  }
-#endif
-  return code;
-}
-
-
-Handle<Code> PropertyAccessCompiler::GetCodeWithFlags(Code::Flags flags,
-                                                      Handle<Name> name) {
-  return (FLAG_print_code_stubs && !name.is_null() && name->IsString())
-             ? GetCodeWithFlags(flags,
-                                Handle<String>::cast(name)->ToCString().get())
-             : GetCodeWithFlags(flags, NULL);
-}
-
-
 #define __ ACCESS_MASM(masm())
 
 
@@ -755,22 +724,6 @@ Handle<Code> PropertyICCompiler::CompileKeyedStoreMonomorphic(
 #undef __
 
 
-void PropertyAccessCompiler::TailCallBuiltin(MacroAssembler* masm,
-                                             Builtins::Name name) {
-  Handle<Code> code(masm->isolate()->builtins()->builtin(name));
-  GenerateTailCall(masm, code);
-}
-
-
-Register* PropertyAccessCompiler::GetCallingConvention(Code::Kind kind) {
-  if (kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC) {
-    return load_calling_convention();
-  }
-  DCHECK(kind == Code::STORE_IC || kind == Code::KEYED_STORE_IC);
-  return store_calling_convention();
-}
-
-
 Handle<Code> PropertyICCompiler::GetCode(Code::Kind kind, Code::StubType type,
                                          Handle<Name> name,
                                          InlineCacheState state) {
@@ -880,104 +833,5 @@ void ElementHandlerCompiler::GenerateStoreDictionaryElement(
 }
 
 
-CallOptimization::CallOptimization(Handle<JSFunction> function) {
-  Initialize(function);
-}
-
-
-Handle<JSObject> CallOptimization::LookupHolderOfExpectedType(
-    Handle<Map> object_map, HolderLookup* holder_lookup) const {
-  DCHECK(is_simple_api_call());
-  if (!object_map->IsJSObjectMap()) {
-    *holder_lookup = kHolderNotFound;
-    return Handle<JSObject>::null();
-  }
-  if (expected_receiver_type_.is_null() ||
-      expected_receiver_type_->IsTemplateFor(*object_map)) {
-    *holder_lookup = kHolderIsReceiver;
-    return Handle<JSObject>::null();
-  }
-  while (true) {
-    if (!object_map->prototype()->IsJSObject()) break;
-    Handle<JSObject> prototype(JSObject::cast(object_map->prototype()));
-    if (!prototype->map()->is_hidden_prototype()) break;
-    object_map = handle(prototype->map());
-    if (expected_receiver_type_->IsTemplateFor(*object_map)) {
-      *holder_lookup = kHolderFound;
-      return prototype;
-    }
-  }
-  *holder_lookup = kHolderNotFound;
-  return Handle<JSObject>::null();
-}
-
-
-bool CallOptimization::IsCompatibleReceiver(Handle<Object> receiver,
-                                            Handle<JSObject> holder) const {
-  DCHECK(is_simple_api_call());
-  if (!receiver->IsJSObject()) return false;
-  Handle<Map> map(JSObject::cast(*receiver)->map());
-  HolderLookup holder_lookup;
-  Handle<JSObject> api_holder = LookupHolderOfExpectedType(map, &holder_lookup);
-  switch (holder_lookup) {
-    case kHolderNotFound:
-      return false;
-    case kHolderIsReceiver:
-      return true;
-    case kHolderFound:
-      if (api_holder.is_identical_to(holder)) return true;
-      // Check if holder is in prototype chain of api_holder.
-      {
-        JSObject* object = *api_holder;
-        while (true) {
-          Object* prototype = object->map()->prototype();
-          if (!prototype->IsJSObject()) return false;
-          if (prototype == *holder) return true;
-          object = JSObject::cast(prototype);
-        }
-      }
-      break;
-  }
-  UNREACHABLE();
-  return false;
-}
-
-
-void CallOptimization::Initialize(Handle<JSFunction> function) {
-  constant_function_ = Handle<JSFunction>::null();
-  is_simple_api_call_ = false;
-  expected_receiver_type_ = Handle<FunctionTemplateInfo>::null();
-  api_call_info_ = Handle<CallHandlerInfo>::null();
-
-  if (function.is_null() || !function->is_compiled()) return;
-
-  constant_function_ = function;
-  AnalyzePossibleApiFunction(function);
-}
-
-
-void CallOptimization::AnalyzePossibleApiFunction(Handle<JSFunction> function) {
-  if (!function->shared()->IsApiFunction()) return;
-  Handle<FunctionTemplateInfo> info(function->shared()->get_api_func_data());
-
-  // Require a C++ callback.
-  if (info->call_code()->IsUndefined()) return;
-  api_call_info_ =
-      Handle<CallHandlerInfo>(CallHandlerInfo::cast(info->call_code()));
-
-  // Accept signatures that either have no restrictions at all or
-  // only have restrictions on the receiver.
-  if (!info->signature()->IsUndefined()) {
-    Handle<SignatureInfo> signature =
-        Handle<SignatureInfo>(SignatureInfo::cast(info->signature()));
-    if (!signature->args()->IsUndefined()) return;
-    if (!signature->receiver()->IsUndefined()) {
-      expected_receiver_type_ = Handle<FunctionTemplateInfo>(
-          FunctionTemplateInfo::cast(signature->receiver()));
-    }
-  }
-
-  is_simple_api_call_ = true;
-}
 }
 }  // namespace v8::internal
index 303e732d14446da5747fd8de811900a605a6dfc0..15e00d231048e5609702923455d10bf3448078b5 100644 (file)
@@ -6,6 +6,7 @@
 #define V8_IC_IC_COMPILER_H_
 
 #include "src/code-stubs.h"
+#include "src/ic/access-compiler.h"
 #include "src/macro-assembler.h"
 #include "src/objects.h"
 
@@ -14,80 +15,12 @@ namespace internal {
 
 
 class CallOptimization;
-class SmallMapList;
-class StubCache;
 
 
 enum PrototypeCheckType { CHECK_ALL_MAPS, SKIP_RECEIVER };
 enum IcCheckType { ELEMENT, PROPERTY };
 
 
-class PropertyAccessCompiler BASE_EMBEDDED {
- public:
-  static Builtins::Name MissBuiltin(Code::Kind kind) {
-    switch (kind) {
-      case Code::LOAD_IC:
-        return Builtins::kLoadIC_Miss;
-      case Code::STORE_IC:
-        return Builtins::kStoreIC_Miss;
-      case Code::KEYED_LOAD_IC:
-        return Builtins::kKeyedLoadIC_Miss;
-      case Code::KEYED_STORE_IC:
-        return Builtins::kKeyedStoreIC_Miss;
-      default:
-        UNREACHABLE();
-    }
-    return Builtins::kLoadIC_Miss;
-  }
-
-  static void TailCallBuiltin(MacroAssembler* masm, Builtins::Name name);
-
- protected:
-  PropertyAccessCompiler(Isolate* isolate, Code::Kind kind,
-                         CacheHolderFlag cache_holder)
-      : registers_(GetCallingConvention(kind)),
-        kind_(kind),
-        cache_holder_(cache_holder),
-        isolate_(isolate),
-        masm_(isolate, NULL, 256) {}
-
-  Code::Kind kind() const { return kind_; }
-  CacheHolderFlag cache_holder() const { return cache_holder_; }
-  MacroAssembler* masm() { return &masm_; }
-  Isolate* isolate() const { return isolate_; }
-  Heap* heap() const { return isolate()->heap(); }
-  Factory* factory() const { return isolate()->factory(); }
-
-  Register receiver() const { return registers_[0]; }
-  Register name() const { return registers_[1]; }
-  Register scratch1() const { return registers_[2]; }
-  Register scratch2() const { return registers_[3]; }
-  Register scratch3() const { return registers_[4]; }
-
-  // Calling convention between indexed store IC and handler.
-  Register transition_map() const { return scratch1(); }
-
-  static Register* GetCallingConvention(Code::Kind);
-  static Register* load_calling_convention();
-  static Register* store_calling_convention();
-  static Register* keyed_store_calling_convention();
-
-  Register* registers_;
-
-  static void GenerateTailCall(MacroAssembler* masm, Handle<Code> code);
-
-  Handle<Code> GetCodeWithFlags(Code::Flags flags, const char* name);
-  Handle<Code> GetCodeWithFlags(Code::Flags flags, Handle<Name> name);
-
- private:
-  Code::Kind kind_;
-  CacheHolderFlag cache_holder_;
-
-  Isolate* isolate_;
-  MacroAssembler masm_;
-};
-
-
 class PropertyICCompiler : public PropertyAccessCompiler {
  public:
   // Finds the Code object stored in the Heap::non_monomorphic_cache().
@@ -451,50 +384,6 @@ class ElementHandlerCompiler : public PropertyHandlerCompiler {
 };
 
 
-// Holds information about possible function call optimizations.
-class CallOptimization BASE_EMBEDDED {
- public:
-  explicit CallOptimization(Handle<JSFunction> function);
-
-  bool is_constant_call() const { return !constant_function_.is_null(); }
-
-  Handle<JSFunction> constant_function() const {
-    DCHECK(is_constant_call());
-    return constant_function_;
-  }
-
-  bool is_simple_api_call() const { return is_simple_api_call_; }
-
-  Handle<FunctionTemplateInfo> expected_receiver_type() const {
-    DCHECK(is_simple_api_call());
-    return expected_receiver_type_;
-  }
-
-  Handle<CallHandlerInfo> api_call_info() const {
-    DCHECK(is_simple_api_call());
-    return api_call_info_;
-  }
-
-  enum HolderLookup { kHolderNotFound, kHolderIsReceiver, kHolderFound };
-  Handle<JSObject> LookupHolderOfExpectedType(
-      Handle<Map> receiver_map, HolderLookup* holder_lookup) const;
-
-  // Check if the api holder is between the receiver and the holder.
-  bool IsCompatibleReceiver(Handle<Object> receiver,
-                            Handle<JSObject> holder) const;
-
- private:
-  void Initialize(Handle<JSFunction> function);
-
-  // Determines whether the given function can be called using the
-  // fast api call builtin.
-  void AnalyzePossibleApiFunction(Handle<JSFunction> function);
-
-  Handle<JSFunction> constant_function_;
-  bool is_simple_api_call_;
-  Handle<FunctionTemplateInfo> expected_receiver_type_;
-  Handle<CallHandlerInfo> api_call_info_;
-};
 }
 }  // namespace v8::internal
 
index 2240abd27ea411bac090a0130a7cb10378de7f1a..4c297ee8ff826be2a1f2ed35a91b2fabab1ae96e 100644 (file)
@@ -10,6 +10,7 @@
 #include "src/codegen.h"
 #include "src/conversions.h"
 #include "src/execution.h"
+#include "src/ic/call-optimization.h"
 #include "src/ic/ic-inl.h"
 #include "src/ic/ic-compiler.h"
 #include "src/ic/stub-cache.h"
diff --git a/src/ic/x64/access-compiler-x64.cc b/src/ic/x64/access-compiler-x64.cc
new file mode 100644 (file)
index 0000000..9014c33
--- /dev/null
@@ -0,0 +1,46 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/v8.h"
+
+#if V8_TARGET_ARCH_X64
+
+#include "src/ic/access-compiler.h"
+
+namespace v8 {
+namespace internal {
+
+#define __ ACCESS_MASM(masm)
+
+
+void PropertyAccessCompiler::GenerateTailCall(MacroAssembler* masm,
+                                              Handle<Code> code) {
+  __ jmp(code, RelocInfo::CODE_TARGET);
+}
+
+
+Register* PropertyAccessCompiler::load_calling_convention() {
+  // receiver, name, scratch1, scratch2, scratch3, scratch4.
+  Register receiver = LoadIC::ReceiverRegister();
+  Register name = LoadIC::NameRegister();
+  static Register registers[] = {receiver, name, rax, rbx, rdi, r8};
+  return registers;
+}
+
+
+Register* PropertyAccessCompiler::store_calling_convention() {
+  // receiver, name, scratch1, scratch2, scratch3.
+  Register receiver = KeyedStoreIC::ReceiverRegister();
+  Register name = KeyedStoreIC::NameRegister();
+  DCHECK(rbx.is(KeyedStoreIC::MapRegister()));
+  static Register registers[] = {receiver, name, rbx, rdi, r8};
+  return registers;
+}
+
+
+#undef __
+}
+}  // namespace v8::internal
+
+#endif  // V8_TARGET_ARCH_X64
index b9fe4788516f9ae1042c0387fd273f25e32f39c6..793bd0efb5dc2fd241579cfcf447d1f8fb9429c8 100644 (file)
@@ -6,6 +6,7 @@
 
 #if V8_TARGET_ARCH_X64
 
+#include "src/ic/call-optimization.h"
 #include "src/ic/ic-compiler.h"
 
 namespace v8 {
@@ -198,12 +199,6 @@ void PropertyHandlerCompiler::GenerateCheckPropertyCell(
 }
 
 
-void PropertyAccessCompiler::GenerateTailCall(MacroAssembler* masm,
-                                              Handle<Code> code) {
-  __ jmp(code, RelocInfo::CODE_TARGET);
-}
-
-
 #undef __
 #define __ ACCESS_MASM((masm()))
 
@@ -768,25 +763,6 @@ Handle<Code> PropertyICCompiler::CompileKeyedStorePolymorphic(
 }
 
 
-Register* PropertyAccessCompiler::load_calling_convention() {
-  // receiver, name, scratch1, scratch2, scratch3, scratch4.
-  Register receiver = LoadIC::ReceiverRegister();
-  Register name = LoadIC::NameRegister();
-  static Register registers[] = {receiver, name, rax, rbx, rdi, r8};
-  return registers;
-}
-
-
-Register* PropertyAccessCompiler::store_calling_convention() {
-  // receiver, name, scratch1, scratch2, scratch3.
-  Register receiver = KeyedStoreIC::ReceiverRegister();
-  Register name = KeyedStoreIC::NameRegister();
-  DCHECK(rbx.is(KeyedStoreIC::MapRegister()));
-  static Register registers[] = {receiver, name, rbx, rdi, r8};
-  return registers;
-}
-
-
 Register NamedStoreHandlerCompiler::value() { return StoreIC::ValueRegister(); }
 
 
index c46345ea95fa1205793c7a575b6e4bc27788a28b..f6279a1c2d04e24291925db52c1bad4de1cb3556 100644 (file)
         '../../src/i18n.h',
         '../../src/icu_util.cc',
         '../../src/icu_util.h',
+        '../../src/ic/access-compiler.cc',
+        '../../src/ic/access-compiler.h',
+        '../../src/ic/call-optimization.cc',
+        '../../src/ic/call-optimization.h',
         '../../src/ic/ic-inl.h',
         '../../src/ic/ic.cc',
         '../../src/ic/ic.h',
             '../../src/compiler/arm/instruction-codes-arm.h',
             '../../src/compiler/arm/instruction-selector-arm.cc',
             '../../src/compiler/arm/linkage-arm.cc',
+            '../../src/ic/arm/access-compiler-arm.cc',
             '../../src/ic/arm/ic-arm.cc',
             '../../src/ic/arm/ic-compiler-arm.cc',
             '../../src/ic/arm/stub-cache-arm.cc',
             '../../src/compiler/arm64/instruction-codes-arm64.h',
             '../../src/compiler/arm64/instruction-selector-arm64.cc',
             '../../src/compiler/arm64/linkage-arm64.cc',
+            '../../src/ic/arm64/access-compiler-arm64.cc',
             '../../src/ic/arm64/ic-arm64.cc',
             '../../src/ic/arm64/ic-compiler-arm64.cc',
             '../../src/ic/arm64/stub-cache-arm64.cc',
             '../../src/compiler/ia32/instruction-codes-ia32.h',
             '../../src/compiler/ia32/instruction-selector-ia32.cc',
             '../../src/compiler/ia32/linkage-ia32.cc',
+            '../../src/ic/ia32/access-compiler-ia32.cc',
             '../../src/ic/ia32/ic-ia32.cc',
             '../../src/ic/ia32/ic-compiler-ia32.cc',
             '../../src/ic/ia32/stub-cache-ia32.cc',
             '../../src/compiler/x64/instruction-codes-x64.h',
             '../../src/compiler/x64/instruction-selector-x64.cc',
             '../../src/compiler/x64/linkage-x64.cc',
+            '../../src/ic/x64/access-compiler-x64.cc',
             '../../src/ic/x64/ic-x64.cc',
             '../../src/ic/x64/ic-compiler-x64.cc',
             '../../src/ic/x64/stub-cache-x64.cc',