Move PropertyAccessCompiler and CallOptimization to their own files
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
This commit is contained in:
parent
082b65c5db
commit
50ea93c614
7
BUILD.gn
7
BUILD.gn
@ -714,6 +714,10 @@ source_set("v8_base") {
|
|||||||
"src/i18n.h",
|
"src/i18n.h",
|
||||||
"src/icu_util.cc",
|
"src/icu_util.cc",
|
||||||
"src/icu_util.h",
|
"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-inl.h",
|
||||||
"src/ic/ic.cc",
|
"src/ic/ic.cc",
|
||||||
"src/ic/ic.h",
|
"src/ic/ic.h",
|
||||||
@ -929,6 +933,7 @@ source_set("v8_base") {
|
|||||||
"src/compiler/x64/instruction-codes-x64.h",
|
"src/compiler/x64/instruction-codes-x64.h",
|
||||||
"src/compiler/x64/instruction-selector-x64.cc",
|
"src/compiler/x64/instruction-selector-x64.cc",
|
||||||
"src/compiler/x64/linkage-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-x64.cc",
|
||||||
"src/ic/x64/ic-compiler-x64.cc",
|
"src/ic/x64/ic-compiler-x64.cc",
|
||||||
"src/ic/x64/stub-cache-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-codes-arm.h",
|
||||||
"src/compiler/arm/instruction-selector-arm.cc",
|
"src/compiler/arm/instruction-selector-arm.cc",
|
||||||
"src/compiler/arm/linkage-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-arm.cc",
|
||||||
"src/ic/arm/ic-compiler-arm.cc",
|
"src/ic/arm/ic-compiler-arm.cc",
|
||||||
"src/ic/arm/stub-cache-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-codes-arm64.h",
|
||||||
"src/compiler/arm64/instruction-selector-arm64.cc",
|
"src/compiler/arm64/instruction-selector-arm64.cc",
|
||||||
"src/compiler/arm64/linkage-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-arm64.cc",
|
||||||
"src/ic/arm64/ic-compiler-arm64.cc",
|
"src/ic/arm64/ic-compiler-arm64.cc",
|
||||||
"src/ic/arm64/stub-cache-arm64.cc",
|
"src/ic/arm64/stub-cache-arm64.cc",
|
||||||
|
@ -34,16 +34,15 @@
|
|||||||
#include "src/hydrogen-sce.h"
|
#include "src/hydrogen-sce.h"
|
||||||
#include "src/hydrogen-store-elimination.h"
|
#include "src/hydrogen-store-elimination.h"
|
||||||
#include "src/hydrogen-uint32-analysis.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/lithium-allocator.h"
|
||||||
#include "src/parser.h"
|
#include "src/parser.h"
|
||||||
#include "src/runtime.h"
|
#include "src/runtime.h"
|
||||||
#include "src/scopeinfo.h"
|
#include "src/scopeinfo.h"
|
||||||
#include "src/scopes.h"
|
#include "src/scopes.h"
|
||||||
#include "src/typing.h"
|
#include "src/typing.h"
|
||||||
// CallOptimization
|
|
||||||
#include "src/ic/ic-compiler.h"
|
|
||||||
// GetRootConstructor
|
|
||||||
#include "src/ic/ic-inl.h"
|
|
||||||
|
|
||||||
#if V8_TARGET_ARCH_IA32
|
#if V8_TARGET_ARCH_IA32
|
||||||
#include "src/ia32/lithium-codegen-ia32.h" // NOLINT
|
#include "src/ia32/lithium-codegen-ia32.h" // NOLINT
|
||||||
|
55
src/ic/access-compiler.cc
Normal file
55
src/ic/access-compiler.cc
Normal file
@ -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
|
83
src/ic/access-compiler.h
Normal file
83
src/ic/access-compiler.h
Normal file
@ -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_
|
46
src/ic/arm/access-compiler-arm.cc
Normal file
46
src/ic/arm/access-compiler-arm.cc
Normal file
@ -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
|
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#if V8_TARGET_ARCH_ARM
|
#if V8_TARGET_ARCH_ARM
|
||||||
|
|
||||||
|
#include "src/ic/call-optimization.h"
|
||||||
#include "src/ic/ic-compiler.h"
|
#include "src/ic/ic-compiler.h"
|
||||||
|
|
||||||
namespace v8 {
|
namespace v8 {
|
||||||
@ -209,12 +210,6 @@ void PropertyHandlerCompiler::GenerateFastApiCall(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PropertyAccessCompiler::GenerateTailCall(MacroAssembler* masm,
|
|
||||||
Handle<Code> code) {
|
|
||||||
__ Jump(code, RelocInfo::CODE_TARGET);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#undef __
|
#undef __
|
||||||
#define __ ACCESS_MASM(masm())
|
#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(); }
|
Register NamedStoreHandlerCompiler::value() { return StoreIC::ValueRegister(); }
|
||||||
|
|
||||||
|
|
||||||
|
53
src/ic/arm64/access-compiler-arm64.cc
Normal file
53
src/ic/arm64/access-compiler-arm64.cc
Normal file
@ -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
|
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#if V8_TARGET_ARCH_ARM64
|
#if V8_TARGET_ARCH_ARM64
|
||||||
|
|
||||||
|
#include "src/ic/call-optimization.h"
|
||||||
#include "src/ic/ic-compiler.h"
|
#include "src/ic/ic-compiler.h"
|
||||||
|
|
||||||
namespace v8 {
|
namespace v8 {
|
||||||
@ -205,12 +206,6 @@ void PropertyHandlerCompiler::GenerateFastApiCall(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PropertyAccessCompiler::GenerateTailCall(MacroAssembler* masm,
|
|
||||||
Handle<Code> code) {
|
|
||||||
__ Jump(code, RelocInfo::CODE_TARGET);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#undef __
|
#undef __
|
||||||
#define __ ACCESS_MASM(masm())
|
#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(); }
|
Register NamedStoreHandlerCompiler::value() { return StoreIC::ValueRegister(); }
|
||||||
|
|
||||||
|
|
||||||
|
113
src/ic/call-optimization.cc
Normal file
113
src/ic/call-optimization.cc
Normal file
@ -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
|
62
src/ic/call-optimization.h
Normal file
62
src/ic/call-optimization.h
Normal file
@ -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_
|
44
src/ic/ia32/access-compiler-ia32.cc
Normal file
44
src/ic/ia32/access-compiler-ia32.cc
Normal file
@ -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
|
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#if V8_TARGET_ARCH_IA32
|
#if V8_TARGET_ARCH_IA32
|
||||||
|
|
||||||
|
#include "src/ic/call-optimization.h"
|
||||||
#include "src/ic/ic-compiler.h"
|
#include "src/ic/ic-compiler.h"
|
||||||
|
|
||||||
namespace v8 {
|
namespace v8 {
|
||||||
@ -206,12 +207,6 @@ void PropertyHandlerCompiler::GenerateCheckPropertyCell(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PropertyAccessCompiler::GenerateTailCall(MacroAssembler* masm,
|
|
||||||
Handle<Code> code) {
|
|
||||||
__ jmp(code, RelocInfo::CODE_TARGET);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#undef __
|
#undef __
|
||||||
#define __ ACCESS_MASM(masm())
|
#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(); }
|
Register NamedStoreHandlerCompiler::value() { return StoreIC::ValueRegister(); }
|
||||||
|
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#include "src/v8.h"
|
#include "src/v8.h"
|
||||||
|
|
||||||
|
#include "src/ic/call-optimization.h"
|
||||||
#include "src/ic/ic-inl.h"
|
#include "src/ic/ic-inl.h"
|
||||||
#include "src/ic/ic-compiler.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,
|
Code* PropertyICCompiler::FindPreMonomorphic(Isolate* isolate, Code::Kind kind,
|
||||||
ExtraICState state) {
|
ExtraICState state) {
|
||||||
Code::Flags flags = Code::ComputeFlags(kind, PREMONOMORPHIC, 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())
|
#define __ ACCESS_MASM(masm())
|
||||||
|
|
||||||
|
|
||||||
@ -755,22 +724,6 @@ Handle<Code> PropertyICCompiler::CompileKeyedStoreMonomorphic(
|
|||||||
#undef __
|
#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<Code> PropertyICCompiler::GetCode(Code::Kind kind, Code::StubType type,
|
||||||
Handle<Name> name,
|
Handle<Name> name,
|
||||||
InlineCacheState state) {
|
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
|
} // namespace v8::internal
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#define V8_IC_IC_COMPILER_H_
|
#define V8_IC_IC_COMPILER_H_
|
||||||
|
|
||||||
#include "src/code-stubs.h"
|
#include "src/code-stubs.h"
|
||||||
|
#include "src/ic/access-compiler.h"
|
||||||
#include "src/macro-assembler.h"
|
#include "src/macro-assembler.h"
|
||||||
#include "src/objects.h"
|
#include "src/objects.h"
|
||||||
|
|
||||||
@ -14,80 +15,12 @@ namespace internal {
|
|||||||
|
|
||||||
|
|
||||||
class CallOptimization;
|
class CallOptimization;
|
||||||
class SmallMapList;
|
|
||||||
class StubCache;
|
|
||||||
|
|
||||||
|
|
||||||
enum PrototypeCheckType { CHECK_ALL_MAPS, SKIP_RECEIVER };
|
enum PrototypeCheckType { CHECK_ALL_MAPS, SKIP_RECEIVER };
|
||||||
enum IcCheckType { ELEMENT, PROPERTY };
|
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 {
|
class PropertyICCompiler : public PropertyAccessCompiler {
|
||||||
public:
|
public:
|
||||||
// Finds the Code object stored in the Heap::non_monomorphic_cache().
|
// 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
|
} // namespace v8::internal
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include "src/codegen.h"
|
#include "src/codegen.h"
|
||||||
#include "src/conversions.h"
|
#include "src/conversions.h"
|
||||||
#include "src/execution.h"
|
#include "src/execution.h"
|
||||||
|
#include "src/ic/call-optimization.h"
|
||||||
#include "src/ic/ic-inl.h"
|
#include "src/ic/ic-inl.h"
|
||||||
#include "src/ic/ic-compiler.h"
|
#include "src/ic/ic-compiler.h"
|
||||||
#include "src/ic/stub-cache.h"
|
#include "src/ic/stub-cache.h"
|
||||||
|
46
src/ic/x64/access-compiler-x64.cc
Normal file
46
src/ic/x64/access-compiler-x64.cc
Normal file
@ -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
|
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#if V8_TARGET_ARCH_X64
|
#if V8_TARGET_ARCH_X64
|
||||||
|
|
||||||
|
#include "src/ic/call-optimization.h"
|
||||||
#include "src/ic/ic-compiler.h"
|
#include "src/ic/ic-compiler.h"
|
||||||
|
|
||||||
namespace v8 {
|
namespace v8 {
|
||||||
@ -198,12 +199,6 @@ void PropertyHandlerCompiler::GenerateCheckPropertyCell(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PropertyAccessCompiler::GenerateTailCall(MacroAssembler* masm,
|
|
||||||
Handle<Code> code) {
|
|
||||||
__ jmp(code, RelocInfo::CODE_TARGET);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#undef __
|
#undef __
|
||||||
#define __ ACCESS_MASM((masm()))
|
#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(); }
|
Register NamedStoreHandlerCompiler::value() { return StoreIC::ValueRegister(); }
|
||||||
|
|
||||||
|
|
||||||
|
@ -599,6 +599,10 @@
|
|||||||
'../../src/i18n.h',
|
'../../src/i18n.h',
|
||||||
'../../src/icu_util.cc',
|
'../../src/icu_util.cc',
|
||||||
'../../src/icu_util.h',
|
'../../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-inl.h',
|
||||||
'../../src/ic/ic.cc',
|
'../../src/ic/ic.cc',
|
||||||
'../../src/ic/ic.h',
|
'../../src/ic/ic.h',
|
||||||
@ -789,6 +793,7 @@
|
|||||||
'../../src/compiler/arm/instruction-codes-arm.h',
|
'../../src/compiler/arm/instruction-codes-arm.h',
|
||||||
'../../src/compiler/arm/instruction-selector-arm.cc',
|
'../../src/compiler/arm/instruction-selector-arm.cc',
|
||||||
'../../src/compiler/arm/linkage-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-arm.cc',
|
||||||
'../../src/ic/arm/ic-compiler-arm.cc',
|
'../../src/ic/arm/ic-compiler-arm.cc',
|
||||||
'../../src/ic/arm/stub-cache-arm.cc',
|
'../../src/ic/arm/stub-cache-arm.cc',
|
||||||
@ -842,6 +847,7 @@
|
|||||||
'../../src/compiler/arm64/instruction-codes-arm64.h',
|
'../../src/compiler/arm64/instruction-codes-arm64.h',
|
||||||
'../../src/compiler/arm64/instruction-selector-arm64.cc',
|
'../../src/compiler/arm64/instruction-selector-arm64.cc',
|
||||||
'../../src/compiler/arm64/linkage-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-arm64.cc',
|
||||||
'../../src/ic/arm64/ic-compiler-arm64.cc',
|
'../../src/ic/arm64/ic-compiler-arm64.cc',
|
||||||
'../../src/ic/arm64/stub-cache-arm64.cc',
|
'../../src/ic/arm64/stub-cache-arm64.cc',
|
||||||
@ -878,6 +884,7 @@
|
|||||||
'../../src/compiler/ia32/instruction-codes-ia32.h',
|
'../../src/compiler/ia32/instruction-codes-ia32.h',
|
||||||
'../../src/compiler/ia32/instruction-selector-ia32.cc',
|
'../../src/compiler/ia32/instruction-selector-ia32.cc',
|
||||||
'../../src/compiler/ia32/linkage-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-ia32.cc',
|
||||||
'../../src/ic/ia32/ic-compiler-ia32.cc',
|
'../../src/ic/ia32/ic-compiler-ia32.cc',
|
||||||
'../../src/ic/ia32/stub-cache-ia32.cc',
|
'../../src/ic/ia32/stub-cache-ia32.cc',
|
||||||
@ -1013,6 +1020,7 @@
|
|||||||
'../../src/compiler/x64/instruction-codes-x64.h',
|
'../../src/compiler/x64/instruction-codes-x64.h',
|
||||||
'../../src/compiler/x64/instruction-selector-x64.cc',
|
'../../src/compiler/x64/instruction-selector-x64.cc',
|
||||||
'../../src/compiler/x64/linkage-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-x64.cc',
|
||||||
'../../src/ic/x64/ic-compiler-x64.cc',
|
'../../src/ic/x64/ic-compiler-x64.cc',
|
||||||
'../../src/ic/x64/stub-cache-x64.cc',
|
'../../src/ic/x64/stub-cache-x64.cc',
|
||||||
|
Loading…
Reference in New Issue
Block a user