"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/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",
"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",
#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
--- /dev/null
+// 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
--- /dev/null
+// 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_
--- /dev/null
+// 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
#if V8_TARGET_ARCH_ARM
+#include "src/ic/call-optimization.h"
#include "src/ic/ic-compiler.h"
namespace v8 {
}
-void PropertyAccessCompiler::GenerateTailCall(MacroAssembler* masm,
- Handle<Code> code) {
- __ Jump(code, RelocInfo::CODE_TARGET);
-}
-
-
#undef __
#define __ ACCESS_MASM(masm())
}
-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(); }
--- /dev/null
+// 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
#if V8_TARGET_ARCH_ARM64
+#include "src/ic/call-optimization.h"
#include "src/ic/ic-compiler.h"
namespace v8 {
}
-void PropertyAccessCompiler::GenerateTailCall(MacroAssembler* masm,
- Handle<Code> code) {
- __ Jump(code, RelocInfo::CODE_TARGET);
-}
-
-
#undef __
#define __ ACCESS_MASM(masm())
}
-// 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(); }
--- /dev/null
+// 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
--- /dev/null
+// 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_
--- /dev/null
+// 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
#if V8_TARGET_ARCH_IA32
+#include "src/ic/call-optimization.h"
#include "src/ic/ic-compiler.h"
namespace v8 {
}
-void PropertyAccessCompiler::GenerateTailCall(MacroAssembler* masm,
- Handle<Code> code) {
- __ jmp(code, RelocInfo::CODE_TARGET);
-}
-
-
#undef __
#define __ ACCESS_MASM(masm())
}
-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(); }
#include "src/v8.h"
+#include "src/ic/call-optimization.h"
#include "src/ic/ic-inl.h"
#include "src/ic/ic-compiler.h"
}
-#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);
}
-#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())
#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) {
}
-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
#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"
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().
};
-// 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
#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"
--- /dev/null
+// 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
#if V8_TARGET_ARCH_X64
+#include "src/ic/call-optimization.h"
#include "src/ic/ic-compiler.h"
namespace v8 {
}
-void PropertyAccessCompiler::GenerateTailCall(MacroAssembler* masm,
- Handle<Code> code) {
- __ jmp(code, RelocInfo::CODE_TARGET);
-}
-
-
#undef __
#define __ ACCESS_MASM((masm()))
}
-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(); }
'../../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',