Commit 10f73fac authored by Michael Starzinger's avatar Michael Starzinger Committed by Commit Bot

[ic] Remove deprecated CompareIC stub support.

R=ishell@chromium.org
BUG=v8:6409

Change-Id: Ic01d4f1a8b251bb5480840d4943d9ebec713b9c1
Reviewed-on: https://chromium-review.googlesource.com/626016Reviewed-by: 's avatarYang Guo <yangguo@chromium.org>
Reviewed-by: 's avatarIgor Sheludko <ishell@chromium.org>
Commit-Queue: Michael Starzinger <mstarzinger@chromium.org>
Cr-Commit-Position: refs/heads/master@{#47534}
parent ae1fc792
......@@ -1651,8 +1651,6 @@ v8_source_set("v8_base") {
"src/ic/handler-configuration.cc",
"src/ic/handler-configuration.h",
"src/ic/ic-inl.h",
"src/ic/ic-state.cc",
"src/ic/ic-state.h",
"src/ic/ic-stats.cc",
"src/ic/ic-stats.h",
"src/ic/ic.cc",
......@@ -2104,7 +2102,6 @@ v8_source_set("v8_base") {
"src/ia32/sse-instr.h",
"src/ic/ia32/access-compiler-ia32.cc",
"src/ic/ia32/handler-compiler-ia32.cc",
"src/ic/ia32/ic-ia32.cc",
"src/regexp/ia32/regexp-macro-assembler-ia32.cc",
"src/regexp/ia32/regexp-macro-assembler-ia32.h",
]
......@@ -2119,7 +2116,6 @@ v8_source_set("v8_base") {
"src/debug/x64/debug-x64.cc",
"src/ic/x64/access-compiler-x64.cc",
"src/ic/x64/handler-compiler-x64.cc",
"src/ic/x64/ic-x64.cc",
"src/regexp/x64/regexp-macro-assembler-x64.cc",
"src/regexp/x64/regexp-macro-assembler-x64.h",
"src/third_party/valgrind/valgrind.h",
......@@ -2178,7 +2174,6 @@ v8_source_set("v8_base") {
"src/debug/arm/debug-arm.cc",
"src/ic/arm/access-compiler-arm.cc",
"src/ic/arm/handler-compiler-arm.cc",
"src/ic/arm/ic-arm.cc",
"src/regexp/arm/regexp-macro-assembler-arm.cc",
"src/regexp/arm/regexp-macro-assembler-arm.h",
]
......@@ -2225,7 +2220,6 @@ v8_source_set("v8_base") {
"src/debug/arm64/debug-arm64.cc",
"src/ic/arm64/access-compiler-arm64.cc",
"src/ic/arm64/handler-compiler-arm64.cc",
"src/ic/arm64/ic-arm64.cc",
"src/regexp/arm64/regexp-macro-assembler-arm64.cc",
"src/regexp/arm64/regexp-macro-assembler-arm64.h",
]
......@@ -2238,7 +2232,6 @@ v8_source_set("v8_base") {
"src/debug/mips/debug-mips.cc",
"src/ic/mips/access-compiler-mips.cc",
"src/ic/mips/handler-compiler-mips.cc",
"src/ic/mips/ic-mips.cc",
"src/mips/assembler-mips-inl.h",
"src/mips/assembler-mips.cc",
"src/mips/assembler-mips.h",
......@@ -2270,7 +2263,6 @@ v8_source_set("v8_base") {
"src/debug/mips64/debug-mips64.cc",
"src/ic/mips64/access-compiler-mips64.cc",
"src/ic/mips64/handler-compiler-mips64.cc",
"src/ic/mips64/ic-mips64.cc",
"src/mips64/assembler-mips64-inl.h",
"src/mips64/assembler-mips64.cc",
"src/mips64/assembler-mips64.h",
......@@ -2302,7 +2294,6 @@ v8_source_set("v8_base") {
"src/debug/ppc/debug-ppc.cc",
"src/ic/ppc/access-compiler-ppc.cc",
"src/ic/ppc/handler-compiler-ppc.cc",
"src/ic/ppc/ic-ppc.cc",
"src/ppc/assembler-ppc-inl.h",
"src/ppc/assembler-ppc.cc",
"src/ppc/assembler-ppc.h",
......@@ -2334,7 +2325,6 @@ v8_source_set("v8_base") {
"src/debug/s390/debug-s390.cc",
"src/ic/s390/access-compiler-s390.cc",
"src/ic/s390/handler-compiler-s390.cc",
"src/ic/s390/ic-s390.cc",
"src/regexp/s390/regexp-macro-assembler-s390.cc",
"src/regexp/s390/regexp-macro-assembler-s390.h",
"src/s390/assembler-s390-inl.h",
......
This diff is collapsed.
This diff is collapsed.
......@@ -148,12 +148,6 @@ Callable CodeFactory::KeyedStoreIC_Megamorphic(Isolate* isolate,
StoreWithVectorDescriptor(isolate));
}
// static
Callable CodeFactory::CompareIC(Isolate* isolate, Token::Value op) {
CompareICStub stub(isolate, op);
return make_callable(stub);
}
// static
Callable CodeFactory::BinaryOperation(Isolate* isolate, Token::Value op) {
switch (op) {
......
......@@ -11,6 +11,7 @@
#include "src/codegen.h"
#include "src/globals.h"
#include "src/interface-descriptors.h"
#include "src/parsing/token.h"
namespace v8 {
namespace internal {
......@@ -46,9 +47,6 @@ class V8_EXPORT_PRIVATE CodeFactory final {
static Callable FrameDropperTrampoline(Isolate* isolate);
static Callable HandleDebuggerStatement(Isolate* isolate);
static Callable CompareIC(Isolate* isolate, Token::Value op);
static Callable CompareNilIC(Isolate* isolate, NilValue nil_value);
static Callable BinaryOperation(Isolate* isolate, Token::Value op);
static Callable ApiGetter(Isolate* isolate);
......
......@@ -318,68 +318,6 @@ TF_STUB(StringAddStub, CodeStubAssembler) {
}
}
InlineCacheState CompareICStub::GetICState() const {
CompareICState::State state = Max(left(), right());
switch (state) {
case CompareICState::UNINITIALIZED:
return ::v8::internal::UNINITIALIZED;
case CompareICState::BOOLEAN:
case CompareICState::SMI:
case CompareICState::NUMBER:
case CompareICState::INTERNALIZED_STRING:
case CompareICState::STRING:
case CompareICState::UNIQUE_NAME:
case CompareICState::RECEIVER:
case CompareICState::KNOWN_RECEIVER:
return MONOMORPHIC;
case CompareICState::GENERIC:
return ::v8::internal::GENERIC;
}
UNREACHABLE();
}
Condition CompareICStub::GetCondition() const {
return CompareIC::ComputeCondition(op());
}
void CompareICStub::Generate(MacroAssembler* masm) {
switch (state()) {
case CompareICState::UNINITIALIZED:
GenerateMiss(masm);
break;
case CompareICState::BOOLEAN:
GenerateBooleans(masm);
break;
case CompareICState::SMI:
GenerateSmis(masm);
break;
case CompareICState::NUMBER:
GenerateNumbers(masm);
break;
case CompareICState::STRING:
GenerateStrings(masm);
break;
case CompareICState::INTERNALIZED_STRING:
GenerateInternalizedStrings(masm);
break;
case CompareICState::UNIQUE_NAME:
GenerateUniqueNames(masm);
break;
case CompareICState::RECEIVER:
GenerateReceivers(masm);
break;
case CompareICState::KNOWN_RECEIVER:
DCHECK(*known_map_ != NULL);
GenerateKnownReceivers(masm);
break;
case CompareICState::GENERIC:
GenerateGeneric(masm);
break;
}
}
Handle<Code> TurboFanCodeStub::GenerateCode() {
const char* name = CodeStub::MajorName(MajorKey());
Zone zone(isolate()->allocator(), ZONE_NAME);
......
......@@ -11,7 +11,6 @@
#include "src/factory.h"
#include "src/find-and-replace-pattern.h"
#include "src/globals.h"
#include "src/ic/ic-state.h"
#include "src/interface-descriptors.h"
#include "src/macro-assembler.h"
#include "src/ostreams.h"
......@@ -35,7 +34,6 @@ class Node;
V(CallApiCallback) \
V(CallApiGetter) \
V(CEntry) \
V(CompareIC) \
V(DoubleToI) \
V(InternalArrayConstructor) \
V(JSEntry) \
......@@ -758,84 +756,6 @@ class StringAddStub final : public TurboFanCodeStub {
};
class CompareICStub : public PlatformCodeStub {
public:
CompareICStub(Isolate* isolate, Token::Value op, CompareICState::State left,
CompareICState::State right, CompareICState::State state)
: PlatformCodeStub(isolate) {
DCHECK(Token::IsCompareOp(op));
DCHECK(OpBits::is_valid(op - Token::EQ));
minor_key_ = OpBits::encode(op - Token::EQ) |
LeftStateBits::encode(left) | RightStateBits::encode(right) |
StateBits::encode(state);
}
// Creates uninitialized compare stub.
CompareICStub(Isolate* isolate, Token::Value op)
: CompareICStub(isolate, op, CompareICState::UNINITIALIZED,
CompareICState::UNINITIALIZED,
CompareICState::UNINITIALIZED) {}
CompareICStub(Isolate* isolate, ExtraICState extra_ic_state)
: PlatformCodeStub(isolate) {
minor_key_ = extra_ic_state;
}
ExtraICState GetExtraICState() const final {
return static_cast<ExtraICState>(minor_key_);
}
void set_known_map(Handle<Map> map) { known_map_ = map; }
InlineCacheState GetICState() const;
Token::Value op() const {
return static_cast<Token::Value>(Token::EQ + OpBits::decode(minor_key_));
}
CompareICState::State left() const {
return LeftStateBits::decode(minor_key_);
}
CompareICState::State right() const {
return RightStateBits::decode(minor_key_);
}
CompareICState::State state() const { return StateBits::decode(minor_key_); }
private:
Code::Kind GetCodeKind() const override { return Code::COMPARE_IC; }
void GenerateBooleans(MacroAssembler* masm);
void GenerateSmis(MacroAssembler* masm);
void GenerateNumbers(MacroAssembler* masm);
void GenerateInternalizedStrings(MacroAssembler* masm);
void GenerateStrings(MacroAssembler* masm);
void GenerateUniqueNames(MacroAssembler* masm);
void GenerateReceivers(MacroAssembler* masm);
void GenerateMiss(MacroAssembler* masm);
void GenerateKnownReceivers(MacroAssembler* masm);
void GenerateGeneric(MacroAssembler* masm);
bool strict() const { return op() == Token::EQ_STRICT; }
Condition GetCondition() const;
// Although we don't cache anything in the special cache we have to define
// this predicate to avoid appearance of code stubs with embedded maps in
// the global stub cache.
bool UseSpecialCache() override {
return state() == CompareICState::KNOWN_RECEIVER;
}
class OpBits : public BitField<int, 0, 3> {};
class LeftStateBits : public BitField<CompareICState::State, 3, 4> {};
class RightStateBits : public BitField<CompareICState::State, 7, 4> {};
class StateBits : public BitField<CompareICState::State, 11, 4> {};
Handle<Map> known_map_;
DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOp);
DEFINE_PLATFORM_CODE_STUB(CompareIC, PlatformCodeStub);
};
class CEntryStub : public PlatformCodeStub {
public:
CEntryStub(Isolate* isolate, int result_size,
......
......@@ -118,10 +118,6 @@ static void PrintRelocInfo(StringBuilder* out, Isolate* isolate,
Code::Kind kind = code->kind();
if (code->is_inline_cache_stub()) {
out->AddFormatted(" %s", Code::Kind2String(kind));
if (kind == Code::COMPARE_IC) {
InlineCacheState ic_state = IC::StateFromCode(code);
out->AddFormatted(" %s", Code::ICState2String(ic_state));
}
} else if (kind == Code::STUB || kind == Code::HANDLER) {
// Get the STUB key and extract major and minor key.
uint32_t key = code->stub_key();
......
......@@ -6,7 +6,6 @@
#include "src/code-stubs.h"
#include "src/feedback-vector-inl.h"
#include "src/ic/ic-inl.h"
#include "src/ic/ic-state.h"
#include "src/objects.h"
#include "src/objects/object-macros.h"
......
......@@ -41,7 +41,6 @@
V(char_at_string, "CharAt") \
V(closure_string, "(closure)") \
V(column_string, "column") \
V(compare_ic_string, "==") \
V(configurable_string, "configurable") \
V(constructor_string, "constructor") \
V(construct_string, "construct") \
......@@ -167,7 +166,6 @@
V(stackTraceLimit_string, "stackTraceLimit") \
V(star_default_star_string, "*default*") \
V(sticky_string, "sticky") \
V(strict_compare_ic_string, "===") \
V(string_string, "string") \
V(String_string, "String") \
V(symbol_string, "symbol") \
......
......@@ -10,7 +10,6 @@
#include "src/heap/array-buffer-tracker.h"
#include "src/heap/embedder-tracing.h"
#include "src/heap/mark-compact.h"
#include "src/ic/ic-state.h"
#include "src/macro-assembler.h"
#include "src/objects-body-descriptors-inl.h"
......
This diff is collapsed.
// Copyright 2012 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.
#if V8_TARGET_ARCH_ARM
#include "src/assembler-inl.h"
#include "src/codegen.h"
#include "src/ic/ic.h"
#include "src/ic/stub-cache.h"
#include "src/objects-inl.h"
namespace v8 {
namespace internal {
Condition CompareIC::ComputeCondition(Token::Value op) {
switch (op) {
case Token::EQ_STRICT:
case Token::EQ:
return eq;
case Token::LT:
return lt;
case Token::GT:
return gt;
case Token::LTE:
return le;
case Token::GTE:
return ge;
default:
UNREACHABLE();
}
}
bool CompareIC::HasInlinedSmiCode(Address address) {
// The address of the instruction following the call.
Address cmp_instruction_address =
Assembler::return_address_from_call_start(address);
// If the instruction following the call is not a cmp rx, #yyy, nothing
// was inlined.
Instr instr = Assembler::instr_at(cmp_instruction_address);
return Assembler::IsCmpImmediate(instr);
}
void PatchInlinedSmiCode(Isolate* isolate, Address address,
InlinedSmiCheck check) {
Address cmp_instruction_address =
Assembler::return_address_from_call_start(address);
// If the instruction following the call is not a cmp rx, #yyy, nothing
// was inlined.
Instr instr = Assembler::instr_at(cmp_instruction_address);
if (!Assembler::IsCmpImmediate(instr)) {
return;
}
// The delta to the start of the map check instruction and the
// condition code uses at the patched jump.
int delta = Assembler::GetCmpImmediateRawImmediate(instr);
delta += Assembler::GetCmpImmediateRegister(instr).code() * kOff12Mask;
// If the delta is 0 the instruction is cmp r0, #0 which also signals that
// nothing was inlined.
if (delta == 0) {
return;
}
if (FLAG_trace_ic) {
LOG(isolate, PatchIC(address, cmp_instruction_address, delta));
}
Address patch_address =
cmp_instruction_address - delta * Instruction::kInstrSize;
Instr instr_at_patch = Assembler::instr_at(patch_address);
Instr branch_instr =
Assembler::instr_at(patch_address + Instruction::kInstrSize);
// This is patching a conditional "jump if not smi/jump if smi" site.
// Enabling by changing from
// cmp rx, rx
// b eq/ne, <target>
// to
// tst rx, #kSmiTagMask
// b ne/eq, <target>
// and vice-versa to be disabled again.
CodePatcher patcher(isolate, patch_address, 2);
Register reg = Assembler::GetRn(instr_at_patch);
if (check == ENABLE_INLINED_SMI_CHECK) {
DCHECK(Assembler::IsCmpRegister(instr_at_patch));
DCHECK_EQ(Assembler::GetRn(instr_at_patch).code(),
Assembler::GetRm(instr_at_patch).code());
patcher.masm()->tst(reg, Operand(kSmiTagMask));
} else {
DCHECK(check == DISABLE_INLINED_SMI_CHECK);
DCHECK(Assembler::IsTstImmediate(instr_at_patch));
patcher.masm()->cmp(reg, reg);
}
DCHECK(Assembler::IsBranch(branch_instr));
if (Assembler::GetCondition(branch_instr) == eq) {
patcher.EmitCondition(ne);
} else {
DCHECK(Assembler::GetCondition(branch_instr) == ne);
patcher.EmitCondition(eq);
}
}
} // namespace internal
} // namespace v8
#endif // V8_TARGET_ARCH_ARM
// Copyright 2013 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.
#if V8_TARGET_ARCH_ARM64
#include "src/arm64/assembler-arm64-inl.h"
#include "src/codegen.h"
#include "src/ic/ic.h"
#include "src/ic/stub-cache.h"
#include "src/objects-inl.h"
namespace v8 {
namespace internal {
Condition CompareIC::ComputeCondition(Token::Value op) {
switch (op) {
case Token::EQ_STRICT:
case Token::EQ:
return eq;
case Token::LT:
return lt;
case Token::GT:
return gt;
case Token::LTE:
return le;
case Token::GTE:
return ge;
default:
UNREACHABLE();
}
}
bool CompareIC::HasInlinedSmiCode(Address address) {
// The address of the instruction following the call.
Address info_address = Assembler::return_address_from_call_start(address);
InstructionSequence* patch_info = InstructionSequence::At(info_address);
return patch_info->IsInlineData();
}
// Activate a SMI fast-path by patching the instructions generated by
// JumpPatchSite::EmitJumpIf(Not)Smi(), using the information encoded by
// JumpPatchSite::EmitPatchInfo().
void PatchInlinedSmiCode(Isolate* isolate, Address address,
InlinedSmiCheck check) {
// The patch information is encoded in the instruction stream using
// instructions which have no side effects, so we can safely execute them.
// The patch information is encoded directly after the call to the helper
// function which is requesting this patch operation.
Address info_address = Assembler::return_address_from_call_start(address);
InlineSmiCheckInfo info(info_address);
// Check and decode the patch information instruction.
if (!info.HasSmiCheck()) {
return;
}
if (FLAG_trace_ic) {
LOG(isolate, PatchIC(address, info_address, info.SmiCheckDelta()));
}
// Patch and activate code generated by JumpPatchSite::EmitJumpIfNotSmi()
// and JumpPatchSite::EmitJumpIfSmi().
// Changing
// tb(n)z xzr, #0, <target>
// to
// tb(!n)z test_reg, #0, <target>
Instruction* to_patch = info.SmiCheck();
PatchingAssembler patcher(isolate, reinterpret_cast<byte*>(to_patch), 1);
DCHECK(to_patch->IsTestBranch());
DCHECK(to_patch->ImmTestBranchBit5() == 0);
DCHECK(to_patch->ImmTestBranchBit40() == 0);
STATIC_ASSERT(kSmiTag == 0);
STATIC_ASSERT(kSmiTagMask == 1);
int branch_imm = to_patch->ImmTestBranch();
Register smi_reg;
if (check == ENABLE_INLINED_SMI_CHECK) {
DCHECK(to_patch->Rt() == xzr.code());
smi_reg = info.SmiRegister();
} else {
DCHECK(check == DISABLE_INLINED_SMI_CHECK);
DCHECK(to_patch->Rt() != xzr.code());
smi_reg = xzr;
}
if (to_patch->Mask(TestBranchMask) == TBZ) {
// This is JumpIfNotSmi(smi_reg, branch_imm).
patcher.tbnz(smi_reg, 0, branch_imm);
} else {
DCHECK(to_patch->Mask(TestBranchMask) == TBNZ);
// This is JumpIfSmi(smi_reg, branch_imm).
patcher.tbz(smi_reg, 0, branch_imm);
}
}
} // namespace internal
} // namespace v8
#endif // V8_TARGET_ARCH_ARM64
......@@ -6,7 +6,6 @@
#define V8_IC_HANDLER_COMPILER_H_
#include "src/ic/access-compiler.h"
#include "src/ic/ic-state.h"
namespace v8 {
namespace internal {
......
// Copyright 2012 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.
#if V8_TARGET_ARCH_IA32
#include "src/codegen.h"
#include "src/ic/ic.h"
#include "src/ic/stub-cache.h"
namespace v8 {
namespace internal {
Condition CompareIC::ComputeCondition(Token::Value op) {
switch (op) {
case Token::EQ_STRICT:
case Token::EQ:
return equal;
case Token::LT:
return less;
case Token::GT:
return greater;
case Token::LTE:
return less_equal;
case Token::GTE:
return greater_equal;
default:
UNREACHABLE();
}
}
bool CompareIC::HasInlinedSmiCode(Address address) {
// The address of the instruction following the call.
Address test_instruction_address =
address + Assembler::kCallTargetAddressOffset;
// If the instruction following the call is not a test al, nothing
// was inlined.
return *test_instruction_address == Assembler::kTestAlByte;
}
void PatchInlinedSmiCode(Isolate* isolate, Address address,
InlinedSmiCheck check) {
// The address of the instruction following the call.
Address test_instruction_address =
address + Assembler::kCallTargetAddressOffset;
// If the instruction following the call is not a test al, nothing
// was inlined.
if (*test_instruction_address != Assembler::kTestAlByte) {
DCHECK(*test_instruction_address == Assembler::kNopByte);
return;
}
Address delta_address = test_instruction_address + 1;
// The delta to the start of the map check instruction and the
// condition code uses at the patched jump.
uint8_t delta = *reinterpret_cast<uint8_t*>(delta_address);
if (FLAG_trace_ic) {
LOG(isolate, PatchIC(address, test_instruction_address, delta));
}
// Patch with a short conditional jump. Enabling means switching from a short
// jump-if-carry/not-carry to jump-if-zero/not-zero, whereas disabling is the
// reverse operation of that.
Address jmp_address = test_instruction_address - delta;
DCHECK((check == ENABLE_INLINED_SMI_CHECK)
? (*jmp_address == Assembler::kJncShortOpcode ||
*jmp_address == Assembler::kJcShortOpcode)
: (*jmp_address == Assembler::kJnzShortOpcode ||
*jmp_address == Assembler::kJzShortOpcode));
Condition cc =
(check == ENABLE_INLINED_SMI_CHECK)
? (*jmp_address == Assembler::kJncShortOpcode ? not_zero : zero)
: (*jmp_address == Assembler::kJnzShortOpcode ? not_carry : carry);
*jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc);
}
} // namespace internal
} // namespace v8
#endif // V8_TARGET_ARCH_IA32
......@@ -40,49 +40,6 @@ Address IC::raw_constant_pool() const {
}
Code* IC::GetTargetAtAddress(Address address, Address constant_pool) {
// Get the target address of the IC.
Address target = Assembler::target_address_at(address, constant_pool);
// Convert target address to the code object. Code::GetCodeFromTargetAddress
// is safe for use during GC where the map might be marked.
Code* result = Code::GetCodeFromTargetAddress(target);
// The result can be an IC dispatcher (for vector-based ICs), an IC handler
// (for old-style patching ICs) or CEntryStub (for IC dispatchers inlined to
// bytecode handlers).
DCHECK(result->is_inline_cache_stub() || result->is_stub());
return result;
}
void IC::SetTargetAtAddress(Address address, Code* target,
Address constant_pool) {
if (AddressIsDeoptimizedCode(target->GetIsolate(), address)) return;
// Only one old-style ICs still does code patching.
DCHECK(target->is_compare_ic_stub());
Heap* heap = target->GetHeap();
Code* old_target = GetTargetAtAddress(address, constant_pool);
Assembler::set_target_address_at(heap->isolate(), address, constant_pool,
target->instruction_start());
if (heap->gc_state() == Heap::MARK_COMPACT) {
heap->mark_compact_collector()->RecordCodeTargetPatch(address, target);
} else {
heap->incremental_marking()->RecordCodeTargetPatch(address, target);
}
PostPatching(address, target, old_target);
}
void IC::set_target(Code* code) {
SetTargetAtAddress(address(), code, constant_pool());
}
Code* IC::target() const {
return GetTargetAtAddress(address(), constant_pool());
}
bool IC::IsHandler(Object* object) {
return (object->IsSmi() && (object != nullptr)) || object->IsTuple2() ||
object->IsTuple3() || object->IsFixedArray() || object->IsWeakCell() ||
......
// 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/ic/ic-state.h"
#include "src/feedback-vector.h"
#include "src/ic/ic.h"
#include "src/objects-inl.h"
namespace v8 {
namespace internal {
// static
void ICUtility::Clear(Isolate* isolate, Address address,
Address constant_pool) {
IC::Clear(isolate, address, constant_pool);
}
const char* CompareICState::GetStateName(State state) {
switch (state) {
case UNINITIALIZED:
return "UNINITIALIZED";
case BOOLEAN:
return "BOOLEAN";
case SMI:
return "SMI";
case NUMBER:
return "NUMBER";
case INTERNALIZED_STRING:
return "INTERNALIZED_STRING";
case STRING:
return "STRING";
case UNIQUE_NAME:
return "UNIQUE_NAME";
case RECEIVER:
return "RECEIVER";
case KNOWN_RECEIVER:
return "KNOWN_RECEIVER";
case GENERIC:
return "GENERIC";
}
UNREACHABLE();
}
CompareICState::State CompareICState::NewInputState(State old_state,
Handle<Object> value) {
switch (old_state) {
case UNINITIALIZED:
if (value->IsBoolean()) return BOOLEAN;
if (value->IsSmi()) return SMI;
if (value->IsHeapNumber()) return NUMBER;
if (value->IsInternalizedString()) return INTERNALIZED_STRING;
if (value->IsString()) return STRING;
if (value->IsSymbol()) return UNIQUE_NAME;
if (value->IsJSReceiver() && !value->IsUndetectable()) {
return RECEIVER;
}
break;
case BOOLEAN:
if (value->IsBoolean()) return BOOLEAN;
break;
case SMI:
if (value->IsSmi()) return SMI;
if (value->IsHeapNumber()) return NUMBER;
break;
case NUMBER:
if (value->IsNumber()) return NUMBER;
break;
case INTERNALIZED_STRING:
if (value->IsInternalizedString()) return INTERNALIZED_STRING;
if (value->IsString()) return STRING;
if (value->IsSymbol()) return UNIQUE_NAME;
break;
case STRING:
if (value->IsString()) return STRING;
break;
case UNIQUE_NAME:
if (value->IsUniqueName()) return UNIQUE_NAME;
break;
case RECEIVER:
if (value->IsJSReceiver() && !value->IsUndetectable()) {
return RECEIVER;
}
break;
case GENERIC:
break;
case KNOWN_RECEIVER:
UNREACHABLE();
break;
}
return GENERIC;
}
// static
CompareICState::State CompareICState::TargetState(
Isolate* isolate, State old_state, State old_left, State old_right,
Token::Value op, bool has_inlined_smi_code, Handle<Object> x,
Handle<Object> y) {
switch (old_state) {
case UNINITIALIZED:
if (x->IsBoolean() && y->IsBoolean()) return BOOLEAN;
if (x->IsSmi() && y->IsSmi()) return SMI;
if (x->IsNumber() && y->IsNumber()) return NUMBER;
if (Token::IsOrderedRelationalCompareOp(op)) {
// Ordered comparisons treat undefined as NaN, so the
// NUMBER stub will do the right thing.
if ((x->IsNumber() && y->IsUndefined(isolate)) ||
(y->IsNumber() && x->IsUndefined(isolate))) {
return NUMBER;
}
}
if (x->IsInternalizedString() && y->IsInternalizedString()) {
// We compare internalized strings as plain ones if we need to determine
// the order in a non-equality compare.
return Token::IsEqualityOp(op) ? INTERNALIZED_STRING : STRING;
}
if (x->IsString() && y->IsString()) return STRING;
if (x->IsJSReceiver() && y->IsJSReceiver()) {
if (x->IsUndetectable() || y->IsUndetectable()) {
return GENERIC;
}
if (Handle<JSReceiver>::cast(x)->map() ==
Handle<JSReceiver>::cast(y)->map()) {
return KNOWN_RECEIVER;
} else {
return Token::IsEqualityOp(op) ? RECEIVER : GENERIC;
}
}
if (!Token::IsEqualityOp(op)) return GENERIC;
if (x->IsUniqueName() && y->IsUniqueName()) return UNIQUE_NAME;
return GENERIC;
case SMI:
return x->IsNumber() && y->IsNumber() ? NUMBER : GENERIC;
case INTERNALIZED_STRING:
DCHECK(Token::IsEqualityOp(op));
if (x->IsString() && y->IsString()) return STRING;
if (x->IsUniqueName() && y->IsUniqueName()) return UNIQUE_NAME;
return GENERIC;
case NUMBER:
// If the failure was due to one side changing from smi to heap number,
// then keep the state (if other changed at the same time, we will get
// a second miss and then go to generic).
if (old_left == SMI && x->IsHeapNumber()) return NUMBER;
if (old_right == SMI && y->IsHeapNumber()) return NUMBER;
return GENERIC;
case KNOWN_RECEIVER:
if (x->IsJSReceiver() && y->IsJSReceiver()) {
return Token::IsEqualityOp(op) ? RECEIVER : GENERIC;
}
return GENERIC;
case BOOLEAN:
case STRING:
case UNIQUE_NAME:
case RECEIVER:
case GENERIC:
return GENERIC;
}
UNREACHABLE();
}
} // namespace internal
} // namespace v8
// Copyright 2012 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_STATE_H_
#define V8_IC_STATE_H_
#include "src/macro-assembler.h"
#include "src/parsing/token.h"
namespace v8 {
namespace internal {
const int kMaxKeyedPolymorphism = 4;
class ICUtility : public AllStatic {
public:
// Clear the inline cache to initial state.
static void Clear(Isolate* isolate, Address address, Address constant_pool);
};
class CompareICState {
public:
// The type/state lattice is defined by the following inequations:
// UNINITIALIZED < ...
// ... < GENERIC
// SMI < NUMBER
// INTERNALIZED_STRING < STRING
// INTERNALIZED_STRING < UNIQUE_NAME
// KNOWN_RECEIVER < RECEIVER
enum State {
UNINITIALIZED,
BOOLEAN,
SMI,
NUMBER,
STRING,
INTERNALIZED_STRING,
UNIQUE_NAME, // Symbol or InternalizedString
RECEIVER, // JSReceiver
KNOWN_RECEIVER, // JSReceiver with specific map (faster check)
GENERIC
};
static State NewInputState(State old_state, Handle<Object> value);
static const char* GetStateName(CompareICState::State state);
static State TargetState(Isolate* isolate, State old_state, State old_left,
State old_right, Token::Value op,
bool has_inlined_smi_code, Handle<Object> x,
Handle<Object> y);
};
} // namespace internal
} // namespace v8
#endif // V8_IC_STATE_H_
......@@ -222,22 +222,10 @@ IC::IC(FrameDepth depth, Isolate* isolate, FeedbackNexus* nexus)
constant_pool_address_ = constant_pool;
}
pc_address_ = StackFrame::ResolveReturnAddressLocation(pc_address);
if (nexus) {
kind_ = nexus->kind();
state_ = nexus->StateFromFeedback();
extra_ic_state_ = kNoExtraICState;
} else {
Code* target = this->target();
Code::Kind kind = target->kind();
if (kind == Code::COMPARE_IC) {
kind_ = FeedbackSlotKind::kCompareOp;
} else {
UNREACHABLE();
kind_ = FeedbackSlotKind::kInvalid;
}
state_ = StateFromCode(target);
extra_ic_state_ = target->extra_ic_state();
}
DCHECK_NOT_NULL(nexus);
kind_ = nexus->kind();
state_ = nexus->StateFromFeedback();
extra_ic_state_ = kNoExtraICState;
old_state_ = state_;
}
......@@ -254,18 +242,6 @@ bool IC::ShouldPushPopSlotAndVector(Code::Kind kind) {
return false;
}
InlineCacheState IC::StateFromCode(Code* code) {
Isolate* isolate = code->GetIsolate();
switch (code->kind()) {
case Code::COMPARE_IC: {
CompareICStub stub(isolate, code->extra_ic_state());
return stub.GetICState();
}
default:
UNREACHABLE();
}
}
JSFunction* IC::GetHostFunction() const {
// Compute the JavaScript frame for the frame pointer of this IC
// structure. We need this to be able to find the function
......@@ -377,40 +353,6 @@ MaybeHandle<Object> IC::ReferenceError(Handle<Name> name) {
}
static void ComputeTypeInfoCountDelta(IC::State old_state, IC::State new_state,
int* polymorphic_delta,
int* generic_delta) {
switch (old_state) {
case UNINITIALIZED:
case PREMONOMORPHIC:
if (new_state == UNINITIALIZED || new_state == PREMONOMORPHIC) break;
if (new_state == MONOMORPHIC || new_state == POLYMORPHIC) {
*polymorphic_delta = 1;
} else if (new_state == MEGAMORPHIC || new_state == GENERIC) {
*generic_delta = 1;
}
break;
case MONOMORPHIC:
case POLYMORPHIC:
if (new_state == MONOMORPHIC || new_state == POLYMORPHIC) break;
*polymorphic_delta = -1;
if (new_state == MEGAMORPHIC || new_state == GENERIC) {
*generic_delta = 1;
}
break;
case MEGAMORPHIC:
case GENERIC:
if (new_state == MEGAMORPHIC || new_state == GENERIC) break;
*generic_delta = -1;
if (new_state == MONOMORPHIC || new_state == POLYMORPHIC) {
*polymorphic_delta = 1;
}
break;
case RECOMPUTE_HANDLER:
UNREACHABLE();
}
}
// static
void IC::OnFeedbackChanged(Isolate* isolate, FeedbackVector* vector,
JSFunction* host_function) {
......@@ -431,66 +373,6 @@ void IC::OnFeedbackChanged(Isolate* isolate, FeedbackVector* vector,
// unoptimized version for the benefit of later inlining.
}
void IC::PostPatching(Address address, Code* target, Code* old_target) {
// Type vector based ICs update these statistics at a different time because
// they don't always patch on state change.
DCHECK(target->kind() == Code::COMPARE_IC);
DCHECK(old_target->is_inline_cache_stub());
DCHECK(target->is_inline_cache_stub());
State old_state = StateFromCode(old_target);
State new_state = StateFromCode(target);
Isolate* isolate = target->GetIsolate();
Code* host =
isolate->inner_pointer_to_code_cache()->GetCacheEntry(address)->code;
if (host->kind() != Code::FUNCTION) return;
// Not all Code objects have TypeFeedbackInfo.
if (host->type_feedback_info()->IsTypeFeedbackInfo()) {
if (FLAG_type_info_threshold > 0) {
int polymorphic_delta = 0; // "Polymorphic" here includes monomorphic.
int generic_delta = 0; // "Generic" here includes megamorphic.
ComputeTypeInfoCountDelta(old_state, new_state, &polymorphic_delta,
&generic_delta);
TypeFeedbackInfo* info =
TypeFeedbackInfo::cast(host->type_feedback_info());
info->change_ic_with_type_info_count(polymorphic_delta);
info->change_ic_generic_count(generic_delta);
}
}
// TODO(leszeks): Normally we would reset profiler ticks here -- but, we don't
// currently have access the the feedback vector from the IC. In practice,
// this is not an issue, as these ICs are only used by asm.js, which shouldn't
// have too many IC changes. This inconsistency should go away once these
// Crankshaft/hydrogen code stubs go away.
isolate->runtime_profiler()->NotifyICChanged();
// TODO(2029): When an optimized function is patched, it would
// be nice to propagate the corresponding type information to its
// unoptimized version for the benefit of later inlining.
}
void IC::Clear(Isolate* isolate, Address address, Address constant_pool) {
Code* target = GetTargetAtAddress(address, constant_pool);
if (target->kind() == Code::COMPARE_IC) {
CompareIC::Clear(isolate, address, target, constant_pool);
}
}
void CompareIC::Clear(Isolate* isolate, Address address, Code* target,
Address constant_pool) {
DCHECK(CodeStub::GetMajorKey(target) == CodeStub::CompareIC);
CompareICStub stub(target->stub_key(), isolate);
// Only clear CompareICs that can retain objects.
if (stub.state() != CompareICState::KNOWN_RECEIVER) return;
SetTargetAtAddress(address, GetRawUninitialized(isolate, stub.op()),
constant_pool);
PatchInlinedSmiCode(isolate, address, DISABLE_INLINED_SMI_CHECK);
}
static bool MigrateDeprecated(Handle<Object> object) {
if (!object->IsJSObject()) return false;
Handle<JSObject> receiver = Handle<JSObject>::cast(object);
......@@ -2590,87 +2472,6 @@ RUNTIME_FUNCTION(Runtime_ElementsTransitionAndStoreIC_Miss) {
}
Code* CompareIC::GetRawUninitialized(Isolate* isolate, Token::Value op) {
CompareICStub stub(isolate, op, CompareICState::UNINITIALIZED,
CompareICState::UNINITIALIZED,
CompareICState::UNINITIALIZED);
Code* code = NULL;
CHECK(stub.FindCodeInCache(&code));
return code;
}
Code* CompareIC::UpdateCaches(Handle<Object> x, Handle<Object> y) {
HandleScope scope(isolate());
CompareICStub old_stub(target()->stub_key(), isolate());
CompareICState::State new_left =
CompareICState::NewInputState(old_stub.left(), x);
CompareICState::State new_right =
CompareICState::NewInputState(old_stub.right(), y);
CompareICState::State state = CompareICState::TargetState(
isolate(), old_stub.state(), old_stub.left(), old_stub.right(), op_,
HasInlinedSmiCode(address()), x, y);
CompareICStub stub(isolate(), op_, new_left, new_right, state);
if (state == CompareICState::KNOWN_RECEIVER) {
stub.set_known_map(
Handle<Map>(Handle<JSReceiver>::cast(x)->map(), isolate()));
}
Handle<Code> new_target = stub.GetCode();
set_target(*new_target);
if (FLAG_ic_stats &
v8::tracing::TracingCategoryObserver::ENABLED_BY_TRACING) {
auto ic_stats = ICStats::instance();
ic_stats->Begin();
ICInfo& ic_info = ic_stats->Current();
ic_info.type = "CompareIC";
JavaScriptFrame::CollectTopFrameForICStats(isolate());
ic_info.state = "((";
ic_info.state += CompareICState::GetStateName(old_stub.left());
ic_info.state += "+";
ic_info.state += CompareICState::GetStateName(old_stub.right());
ic_info.state += "=";
ic_info.state += CompareICState::GetStateName(old_stub.state());
ic_info.state += ")->(";
ic_info.state += CompareICState::GetStateName(new_left);
ic_info.state += "+";
ic_info.state += CompareICState::GetStateName(new_right);
ic_info.state += "=";
ic_info.state += CompareICState::GetStateName(state);
ic_info.state += "))#";
ic_info.state += Token::Name(op_);
ic_stats->End();
} else if (FLAG_ic_stats) {
int line;
int column;
Address pc = GetAbstractPC(&line, &column);
LOG(isolate(),
CompareIC(pc, line, column, *stub.GetCode(), Token::Name(op_),
CompareICState::GetStateName(old_stub.left()),
CompareICState::GetStateName(old_stub.right()),
CompareICState::GetStateName(old_stub.state()),
CompareICState::GetStateName(new_left),
CompareICState::GetStateName(new_right),
CompareICState::GetStateName(state)));
}
// Activate inlined smi code.
if (old_stub.state() == CompareICState::UNINITIALIZED) {
PatchInlinedSmiCode(isolate(), address(), ENABLE_INLINED_SMI_CHECK);
}
return *new_target;
}
// Used from CompareICStub::GenerateMiss in code-stubs-<arch>.cc.
RUNTIME_FUNCTION(Runtime_CompareIC_Miss) {
HandleScope scope(isolate);
DCHECK(args.length() == 3);
CompareIC ic(isolate, static_cast<Token::Value>(args.smi_at(2)));
return ic.UpdateCaches(args.at(0), args.at(1));
}
RUNTIME_FUNCTION(Runtime_Unreachable) {
UNREACHABLE();
CHECK(false);
......
......@@ -7,7 +7,6 @@
#include "src/factory.h"
#include "src/feedback-vector.h"
#include "src/ic/ic-state.h"
#include "src/macro-assembler.h"
#include "src/messages.h"
#include "src/objects/map.h"
......@@ -27,6 +26,8 @@ class IC {
// or with a single extra frame for supporting calls.
enum FrameDepth { NO_EXTRA_FRAME = 0, EXTRA_CALL_FRAME = 1 };
static constexpr int kMaxKeyedPolymorphism = 4;
// A polymorphic IC can handle at most 4 distinct maps before transitioning
// to megamorphic state.
static constexpr int kMaxPolymorphicMapCount = 4;
......@@ -49,9 +50,6 @@ class IC {
state_ = RECOMPUTE_HANDLER;
}
// Clear the inline cache to initial state.
static void Clear(Isolate* isolate, Address address, Address constant_pool);
bool IsAnyLoad() const {
return IsLoadIC() || IsLoadGlobalIC() || IsKeyedLoadIC();
}
......@@ -64,8 +62,6 @@ class IC {
// save/restore them in the dispatcher.
static bool ShouldPushPopSlotAndVector(Code::Kind kind);
static InlineCacheState StateFromCode(Code* code);
static inline bool IsHandler(Object* object);
// Nofity the IC system that a feedback has changed.
......@@ -88,8 +84,6 @@ class IC {
inline static bool AddressIsDeoptimizedCode(Isolate* isolate,
Address address);
// Set the call-site target.
inline void set_target(Code* code);
bool is_vector_set() { return vector_set_; }
// Configure for most states.
......@@ -110,13 +104,6 @@ class IC {
Handle<Object> object, Handle<Object> key);
MaybeHandle<Object> ReferenceError(Handle<Name> name);
// Access the target code for the given IC address.
static inline Code* GetTargetAtAddress(Address address,
Address constant_pool);
static inline void SetTargetAtAddress(Address address, Code* target,
Address constant_pool);
static void PostPatching(Address address, Code* target, Code* old_target);
void TraceHandlerCacheHitStats(LookupIterator* lookup);
// Compute the handler either by compiling or by retrieving a cached version.
......@@ -188,8 +175,6 @@ class IC {
}
FeedbackNexus* nexus() const { return nexus_; }
inline Code* target() const;
private:
inline Address constant_pool() const;
inline Address raw_constant_pool() const;
......@@ -424,39 +409,6 @@ class KeyedStoreIC : public StoreIC {
friend class IC;
};
class CompareIC : public IC {
public:
CompareIC(Isolate* isolate, Token::Value op)
: IC(EXTRA_CALL_FRAME, isolate), op_(op) {}
// Update the inline cache for the given operands.
Code* UpdateCaches(Handle<Object> x, Handle<Object> y);
// Helper function for computing the condition for a compare operation.
static Condition ComputeCondition(Token::Value op);
private:
static bool HasInlinedSmiCode(Address address);
bool strict() const { return op_ == Token::EQ_STRICT; }
Condition GetCondition() const { return ComputeCondition(op_); }
static Code* GetRawUninitialized(Isolate* isolate, Token::Value op);
static void Clear(Isolate* isolate, Address address, Code* target,
Address constant_pool);
Token::Value op_;
friend class IC;
};
// Helper for CompareIC.
enum InlinedSmiCheck { ENABLE_INLINED_SMI_CHECK, DISABLE_INLINED_SMI_CHECK };
void PatchInlinedSmiCode(Isolate* isolate, Address address,
InlinedSmiCheck check);
} // namespace internal
} // namespace v8
......
// Copyright 2012 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.
#if V8_TARGET_ARCH_MIPS
#include "src/codegen.h"
#include "src/ic/ic.h"
#include "src/ic/stub-cache.h"
namespace v8 {
namespace internal {
Condition CompareIC::ComputeCondition(Token::Value op) {
switch (op) {
case Token::EQ_STRICT:
case Token::EQ:
return eq;
case Token::LT:
return lt;
case Token::GT:
return gt;
case Token::LTE:
return le;
case Token::GTE:
return ge;
default:
UNREACHABLE();
}
}
bool CompareIC::HasInlinedSmiCode(Address address) {
// The address of the instruction following the call.
Address andi_instruction_address =
address + Assembler::kCallTargetAddressOffset;
// If the instruction following the call is not a andi at, rx, #yyy, nothing
// was inlined.
Instr instr = Assembler::instr_at(andi_instruction_address);
return Assembler::IsAndImmediate(instr) &&
Assembler::GetRt(instr) == static_cast<uint32_t>(zero_reg.code());
}
void PatchInlinedSmiCode(Isolate* isolate, Address address,
InlinedSmiCheck check) {
Address andi_instruction_address =
address + Assembler::kCallTargetAddressOffset;
// If the instruction following the call is not a andi at, rx, #yyy, nothing
// was inlined.
Instr instr = Assembler::instr_at(andi_instruction_address);
if (!(Assembler::IsAndImmediate(instr) &&
Assembler::GetRt(instr) == static_cast<uint32_t>(zero_reg.code()))) {
return;
}
// The delta to the start of the map check instruction and the
// condition code uses at the patched jump.
int delta = Assembler::GetImmediate16(instr);
delta += Assembler::GetRs(instr) * kImm16Mask;
// If the delta is 0 the instruction is andi at, zero_reg, #0 which also
// signals that nothing was inlined.
if (delta == 0) {
return;
}
if (FLAG_trace_ic) {
LOG(isolate, PatchIC(address, andi_instruction_address, delta));
}
Address patch_address =
andi_instruction_address - delta * Instruction::kInstrSize;
Instr instr_at_patch = Assembler::instr_at(patch_address);
// This is patching a conditional "jump if not smi/jump if smi" site.
// Enabling by changing from
// andi at, rx, 0
// Branch <target>, eq, at, Operand(zero_reg)
// to:
// andi at, rx, #kSmiTagMask
// Branch <target>, ne, at, Operand(zero_reg)
// and vice-versa to be disabled again.
CodePatcher patcher(isolate, patch_address, 2);
Register reg = Register::from_code(Assembler::GetRs(instr_at_patch));
if (check == ENABLE_INLINED_SMI_CHECK) {
DCHECK(Assembler::IsAndImmediate(instr_at_patch));
DCHECK_EQ(0u, Assembler::GetImmediate16(instr_at_patch));
patcher.masm()->andi(at, reg, kSmiTagMask);
} else {
DCHECK_EQ(check, DISABLE_INLINED_SMI_CHECK);
DCHECK(Assembler::IsAndImmediate(instr_at_patch));
patcher.masm()->andi(at, reg, 0);
}
Instr branch_instr =
Assembler::instr_at(patch_address + Instruction::kInstrSize);
DCHECK(Assembler::IsBranch(branch_instr));
uint32_t opcode = Assembler::GetOpcodeField(branch_instr);
// Currently only the 'eq' and 'ne' cond values are supported and the simple
// branch instructions and their r6 variants (with opcode being the branch
// type). There are some special cases (see Assembler::IsBranch()) so
// extending this would be tricky.
DCHECK(opcode == BEQ || // BEQ
opcode == BNE || // BNE
opcode == POP10 || // BEQC
opcode == POP30 || // BNEC
opcode == POP66 || // BEQZC
opcode == POP76); // BNEZC
switch (opcode) {
case BEQ:
opcode = BNE; // change BEQ to BNE.
break;
case POP10:
opcode = POP30; // change BEQC to BNEC.
break;
case POP66:
opcode = POP76; // change BEQZC to BNEZC.
break;
case BNE:
opcode = BEQ; // change BNE to BEQ.
break;
case POP30:
opcode = POP10; // change BNEC to BEQC.
break;
case POP76:
opcode = POP66; // change BNEZC to BEQZC.
break;
default:
UNIMPLEMENTED();
}
patcher.ChangeBranchCondition(branch_instr, opcode);
}
} // namespace internal
} // namespace v8
#endif // V8_TARGET_ARCH_MIPS
// Copyright 2012 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.
#if V8_TARGET_ARCH_MIPS64
#include "src/codegen.h"
#include "src/ic/ic.h"
#include "src/ic/stub-cache.h"
namespace v8 {
namespace internal {
Condition CompareIC::ComputeCondition(Token::Value op) {
switch (op) {
case Token::EQ_STRICT:
case Token::EQ:
return eq;
case Token::LT:
return lt;
case Token::GT:
return gt;
case Token::LTE:
return le;
case Token::GTE:
return ge;
default:
UNREACHABLE();
}
}
bool CompareIC::HasInlinedSmiCode(Address address) {
// The address of the instruction following the call.
Address andi_instruction_address =
address + Assembler::kCallTargetAddressOffset;
// If the instruction following the call is not a andi at, rx, #yyy, nothing
// was inlined.
Instr instr = Assembler::instr_at(andi_instruction_address);
return Assembler::IsAndImmediate(instr) &&
Assembler::GetRt(instr) == static_cast<uint32_t>(zero_reg.code());
}
void PatchInlinedSmiCode(Isolate* isolate, Address address,
InlinedSmiCheck check) {
Address andi_instruction_address =
address + Assembler::kCallTargetAddressOffset;
// If the instruction following the call is not a andi at, rx, #yyy, nothing
// was inlined.
Instr instr = Assembler::instr_at(andi_instruction_address);
if (!(Assembler::IsAndImmediate(instr) &&
Assembler::GetRt(instr) == static_cast<uint32_t>(zero_reg.code()))) {
return;
}
// The delta to the start of the map check instruction and the
// condition code uses at the patched jump.
int delta = Assembler::GetImmediate16(instr);
delta += Assembler::GetRs(instr) * kImm16Mask;
// If the delta is 0 the instruction is andi at, zero_reg, #0 which also
// signals that nothing was inlined.
if (delta == 0) {
return;
}
if (FLAG_trace_ic) {
LOG(isolate, PatchIC(address, andi_instruction_address, delta));
}
Address patch_address =
andi_instruction_address - delta * Instruction::kInstrSize;
Instr instr_at_patch = Assembler::instr_at(patch_address);
// This is patching a conditional "jump if not smi/jump if smi" site.
// Enabling by changing from
// andi at, rx, 0
// Branch <target>, eq, at, Operand(zero_reg)
// to:
// andi at, rx, #kSmiTagMask
// Branch <target>, ne, at, Operand(zero_reg)
// and vice-versa to be disabled again.
CodePatcher patcher(isolate, patch_address, 2);
Register reg = Register::from_code(Assembler::GetRs(instr_at_patch));
if (check == ENABLE_INLINED_SMI_CHECK) {
DCHECK(Assembler::IsAndImmediate(instr_at_patch));
DCHECK_EQ(0u, Assembler::GetImmediate16(instr_at_patch));
patcher.masm()->andi(at, reg, kSmiTagMask);
} else {
DCHECK_EQ(check, DISABLE_INLINED_SMI_CHECK);
DCHECK(Assembler::IsAndImmediate(instr_at_patch));
patcher.masm()->andi(at, reg, 0);
}
Instr branch_instr =
Assembler::instr_at(patch_address + Instruction::kInstrSize);
DCHECK(Assembler::IsBranch(branch_instr));
uint32_t opcode = Assembler::GetOpcodeField(branch_instr);
// Currently only the 'eq' and 'ne' cond values are supported and the simple
// branch instructions and their r6 variants (with opcode being the branch
// type). There are some special cases (see Assembler::IsBranch()) so
// extending this would be tricky.
DCHECK(opcode == BEQ || // BEQ
opcode == BNE || // BNE
opcode == POP10 || // BEQC
opcode == POP30 || // BNEC
opcode == POP66 || // BEQZC
opcode == POP76); // BNEZC
switch (opcode) {
case BEQ:
opcode = BNE; // change BEQ to BNE.
break;
case POP10:
opcode = POP30; // change BEQC to BNEC.
break;
case POP66:
opcode = POP76; // change BEQZC to BNEZC.
break;
case BNE:
opcode = BEQ; // change BNE to BEQ.
break;
case POP30:
opcode = POP10; // change BNEC to BEQC.
break;
case POP76:
opcode = POP66; // change BNEZC to BEQZC.
break;
default:
UNIMPLEMENTED();
}
patcher.ChangeBranchCondition(branch_instr, opcode);
}
} // namespace internal
} // namespace v8
#endif // V8_TARGET_ARCH_MIPS64
// 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.
#if V8_TARGET_ARCH_PPC
#include "src/codegen.h"
#include "src/ic/ic.h"
#include "src/ic/stub-cache.h"
namespace v8 {
namespace internal {
Condition CompareIC::ComputeCondition(Token::Value op) {
switch (op) {
case Token::EQ_STRICT:
case Token::EQ:
return eq;
case Token::LT:
return lt;
case Token::GT:
return gt;
case Token::LTE:
return le;
case Token::GTE:
return ge;
default:
UNREACHABLE();
}
}
bool CompareIC::HasInlinedSmiCode(Address address) {
// The address of the instruction following the call.
Address cmp_instruction_address =
Assembler::return_address_from_call_start(address);
// If the instruction following the call is not a cmp rx, #yyy, nothing
// was inlined.
Instr instr = Assembler::instr_at(cmp_instruction_address);
return Assembler::IsCmpImmediate(instr);
}
//
// This code is paired with the JumpPatchSite class in full-codegen-ppc.cc
//
void PatchInlinedSmiCode(Isolate* isolate, Address address,
InlinedSmiCheck check) {
Address cmp_instruction_address =
Assembler::return_address_from_call_start(address);
// If the instruction following the call is not a cmp rx, #yyy, nothing
// was inlined.
Instr instr = Assembler::instr_at(cmp_instruction_address);
if (!Assembler::IsCmpImmediate(instr)) {
return;
}
// The delta to the start of the map check instruction and the
// condition code uses at the patched jump.
int delta = Assembler::GetCmpImmediateRawImmediate(instr);
delta += Assembler::GetCmpImmediateRegister(instr).code() * kOff16Mask;
// If the delta is 0 the instruction is cmp r0, #0 which also signals that
// nothing was inlined.
if (delta == 0) {
return;
}
if (FLAG_trace_ic) {
LOG(isolate, PatchIC(address, cmp_instruction_address, delta));
}
Address patch_address =
cmp_instruction_address - delta * Instruction::kInstrSize;
Instr instr_at_patch = Assembler::instr_at(patch_address);
Instr branch_instr =
Assembler::instr_at(patch_address + Instruction::kInstrSize);
// This is patching a conditional "jump if not smi/jump if smi" site.
// Enabling by changing from
// cmp cr0, rx, rx
// to
// rlwinm(r0, value, 0, 31, 31, SetRC);
// bc(label, BT/BF, 2)
// and vice-versa to be disabled again.
CodePatcher patcher(isolate, patch_address, 2);
Register reg = Assembler::GetRA(instr_at_patch);
if (check == ENABLE_INLINED_SMI_CHECK) {
DCHECK(Assembler::IsCmpRegister(instr_at_patch));
DCHECK_EQ(Assembler::GetRA(instr_at_patch).code(),
Assembler::GetRB(instr_at_patch).code());
patcher.masm()->TestIfSmi(reg, r0);
} else {
DCHECK(check == DISABLE_INLINED_SMI_CHECK);
DCHECK(Assembler::IsAndi(instr_at_patch));
patcher.masm()->cmp(reg, reg, cr0);
}
DCHECK(Assembler::IsBranch(branch_instr));
// Invert the logic of the branch
if (Assembler::GetCondition(branch_instr) == eq) {
patcher.EmitCondition(ne);
} else {
DCHECK(Assembler::GetCondition(branch_instr) == ne);
patcher.EmitCondition(eq);
}
}
} // namespace internal
} // namespace v8
#endif // V8_TARGET_ARCH_PPC
// Copyright 2015 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.
#if V8_TARGET_ARCH_S390
#include "src/ic/ic.h"
#include "src/codegen.h"
#include "src/ic/stub-cache.h"
namespace v8 {
namespace internal {
Condition CompareIC::ComputeCondition(Token::Value op) {
switch (op) {
case Token::EQ_STRICT:
case Token::EQ:
return eq;
case Token::LT:
return lt;
case Token::GT:
return gt;
case Token::LTE:
return le;
case Token::GTE:
return ge;
default:
UNREACHABLE();
}
}
bool CompareIC::HasInlinedSmiCode(Address address) {
// The address of the instruction following the call.
Address cmp_instruction_address =
Assembler::return_address_from_call_start(address);
// If the instruction following the call is not a CHI, nothing
// was inlined.
return (Instruction::S390OpcodeValue(cmp_instruction_address) == CHI);
}
//
// This code is paired with the JumpPatchSite class in full-codegen-s390.cc
//
void PatchInlinedSmiCode(Isolate* isolate, Address address,
InlinedSmiCheck check) {
Address cmp_instruction_address =
Assembler::return_address_from_call_start(address);
// If the instruction following the call is not a cmp rx, #yyy, nothing
// was inlined.
Instr instr = Assembler::instr_at(cmp_instruction_address);
if (Instruction::S390OpcodeValue(cmp_instruction_address) != CHI) {
return;
}
if (Instruction::S390OpcodeValue(address) != BRASL) {
return;
}
// The delta to the start of the map check instruction and the
// condition code uses at the patched jump.
int delta = instr & 0x0000ffff;
// If the delta is 0 the instruction is cmp r0, #0 which also signals that
// nothing was inlined.
if (delta == 0) {
return;
}
if (FLAG_trace_ic) {
LOG(isolate, PatchIC(address, cmp_instruction_address, delta));
}
// Expected sequence to enable by changing the following
// CR/CGR Rx, Rx // 2 / 4 bytes
// LR R0, R0 // 2 bytes // 31-bit only!
// BRC/BRCL // 4 / 6 bytes
// into
// TMLL Rx, XXX // 4 bytes
// BRC/BRCL // 4 / 6 bytes
// And vice versa to disable.
// The following constant is the size of the CR/CGR + LR + LR
const int kPatchAreaSizeNoBranch = 4;
Address patch_address = cmp_instruction_address - delta;
Address branch_address = patch_address + kPatchAreaSizeNoBranch;
Instr instr_at_patch = Assembler::instr_at(patch_address);
SixByteInstr branch_instr = Assembler::instr_at(branch_address);
// This is patching a conditional "jump if not smi/jump if smi" site.
size_t patch_size = 0;
if (Instruction::S390OpcodeValue(branch_address) == BRC) {
patch_size = kPatchAreaSizeNoBranch + 4;
} else if (Instruction::S390OpcodeValue(branch_address) == BRCL) {
patch_size = kPatchAreaSizeNoBranch + 6;
} else {
DCHECK(false);
}
CodePatcher patcher(isolate, patch_address, patch_size);
Register reg;
reg.reg_code = instr_at_patch & 0xf;
if (check == ENABLE_INLINED_SMI_CHECK) {
patcher.masm()->TestIfSmi(reg);
} else {
// Emit the NOP to ensure sufficient place for patching
// (replaced by LR + NILL)
DCHECK(check == DISABLE_INLINED_SMI_CHECK);
patcher.masm()->CmpP(reg, reg);
#ifndef V8_TARGET_ARCH_S390X
patcher.masm()->nop();
#endif
}
Condition cc = al;
if (Instruction::S390OpcodeValue(branch_address) == BRC) {
cc = static_cast<Condition>((branch_instr & 0x00f00000) >> 20);
DCHECK((cc == ne) || (cc == eq));
cc = (cc == ne) ? eq : ne;
patcher.masm()->brc(cc, Operand(branch_instr & 0xffff));
} else if (Instruction::S390OpcodeValue(branch_address) == BRCL) {
cc = static_cast<Condition>(
(branch_instr & (static_cast<uint64_t>(0x00f0) << 32)) >> 36);
DCHECK((cc == ne) || (cc == eq));
cc = (cc == ne) ? eq : ne;
patcher.masm()->brcl(cc, Operand(branch_instr & 0xffffffff));
} else {
DCHECK(false);
}
}
} // namespace internal
} // namespace v8
#endif // V8_TARGET_ARCH_S390
// Copyright 2012 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.
#if V8_TARGET_ARCH_X64
#include "src/codegen.h"
#include "src/ic/ic.h"
#include "src/ic/stub-cache.h"
#include "src/objects-inl.h"
namespace v8 {
namespace internal {
Condition CompareIC::ComputeCondition(Token::Value op) {
switch (op) {
case Token::EQ_STRICT:
case Token::EQ:
return equal;
case Token::LT:
return less;
case Token::GT:
return greater;
case Token::LTE:
return less_equal;
case Token::GTE:
return greater_equal;
default:
UNREACHABLE();
}
}
bool CompareIC::HasInlinedSmiCode(Address address) {
// The address of the instruction following the call.
Address test_instruction_address =
address + Assembler::kCallTargetAddressOffset;
// If the instruction following the call is not a test al, nothing
// was inlined.
return *test_instruction_address == Assembler::kTestAlByte;
}
void PatchInlinedSmiCode(Isolate* isolate, Address address,
InlinedSmiCheck check) {
// The address of the instruction following the call.
Address test_instruction_address =
address + Assembler::kCallTargetAddressOffset;
// If the instruction following the call is not a test al, nothing
// was inlined.
if (*test_instruction_address != Assembler::kTestAlByte) {
DCHECK(*test_instruction_address == Assembler::kNopByte);
return;
}
Address delta_address = test_instruction_address + 1;
// The delta to the start of the map check instruction and the
// condition code uses at the patched jump.
uint8_t delta = *reinterpret_cast<uint8_t*>(delta_address);
if (FLAG_trace_ic) {
LOG(isolate, PatchIC(address, test_instruction_address, delta));
}
// Patch with a short conditional jump. Enabling means switching from a short
// jump-if-carry/not-carry to jump-if-zero/not-zero, whereas disabling is the
// reverse operation of that.
Address jmp_address = test_instruction_address - delta;
DCHECK((check == ENABLE_INLINED_SMI_CHECK)
? (*jmp_address == Assembler::kJncShortOpcode ||
*jmp_address == Assembler::kJcShortOpcode)
: (*jmp_address == Assembler::kJnzShortOpcode ||
*jmp_address == Assembler::kJzShortOpcode));
Condition cc =
(check == ENABLE_INLINED_SMI_CHECK)
? (*jmp_address == Assembler::kJncShortOpcode ? not_zero : zero)
: (*jmp_address == Assembler::kJnzShortOpcode ? not_carry : carry);
*jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc);
}
} // namespace internal
} // namespace v8
#endif // V8_TARGET_ARCH_X64
......@@ -1481,34 +1481,6 @@ void Logger::ICEvent(const char* type, bool keyed, const Address pc, int line,
msg.WriteToLogFile();
}
void Logger::CompareIC(const Address pc, int line, int column, Code* stub,
const char* op, const char* old_left,
const char* old_right, const char* old_state,
const char* new_left, const char* new_right,
const char* new_state) {
if (!log_->IsEnabled() || !FLAG_trace_ic) return;
Log::MessageBuilder msg(log_);
msg.Append("CompareIC,");
msg.AppendAddress(pc);
msg.Append(",%d,%d,", line, column);
msg.AppendAddress(reinterpret_cast<Address>(stub));
msg.Append(",%s,%s,%s,%s,%s,%s,%s", op, old_left, old_right, old_state,
new_left, new_right, new_state);
msg.WriteToLogFile();
}
void Logger::PatchIC(const Address pc, const Address test, int delta) {
if (!log_->IsEnabled() || !FLAG_trace_ic) return;
Log::MessageBuilder msg(log_);
msg.Append("PatchIC,");
msg.AppendAddress(pc);
msg.Append(",");
msg.AppendAddress(test);
msg.Append(",");
msg.Append("%d,", delta);
msg.WriteToLogFile();
}
void Logger::StopProfiler() {
if (!log_->IsEnabled()) return;
if (profiler_ != NULL) {
......@@ -1615,8 +1587,6 @@ void Logger::LogCodeObject(Object* object) {
return; // We log this later using LogCompiledFunctions.
case AbstractCode::BYTECODE_HANDLER:
return; // We log it later by walking the dispatch table.
case AbstractCode::COMPARE_IC: // fall through
case AbstractCode::STUB:
description =
CodeStub::MajorName(CodeStub::GetMajorKey(code_object->GetCode()));
......
......@@ -193,11 +193,6 @@ class Logger : public CodeEventListener {
int column, Map* map, Object* key, char old_state,
char new_state, const char* modifier,
const char* slow_stub_reason);
void CompareIC(const Address pc, int line, int column, Code* stub,
const char* op, const char* old_left, const char* old_right,
const char* old_state, const char* new_left,
const char* new_right, const char* new_state);
void PatchIC(const Address pc, const Address test, int delta);
// ==== Events logged by --log-gc. ====
// Heap sampling events: start, end, and individual types.
......
This diff is collapsed.
This diff is collapsed.
......@@ -3725,11 +3725,6 @@ bool Code::IsCodeStubOrIC() const {
}
}
ExtraICState Code::extra_ic_state() const {
DCHECK(is_compare_ic_stub());
return ExtractExtraICStateFromFlags(flags());
}
// For initialization.
void Code::set_raw_kind_specific_flags1(int value) {
......@@ -3938,8 +3933,6 @@ bool Code::back_edges_patched_for_osr() const {
}
uint16_t Code::to_boolean_state() { return extra_ic_state(); }
bool Code::marked_for_deoptimization() const {
DCHECK(kind() == OPTIMIZED_FUNCTION);
return MarkedForDeoptimizationField::decode(
......@@ -3981,7 +3974,6 @@ bool Code::is_inline_cache_stub() const {
bool Code::is_handler() const { return kind() == HANDLER; }
bool Code::is_stub() const { return kind() == STUB; }
bool Code::is_compare_ic_stub() const { return kind() == COMPARE_IC; }
bool Code::is_optimized_code() const { return kind() == OPTIMIZED_FUNCTION; }
bool Code::is_wasm_code() const { return kind() == WASM_FUNCTION; }
......
......@@ -14097,18 +14097,6 @@ void Code::FindAndReplace(const FindAndReplacePattern& pattern) {
}
void Code::ClearInlineCaches() {
int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET);
for (RelocIterator it(this, mask); !it.done(); it.next()) {
RelocInfo* info = it.rinfo();
Code* target(Code::GetCodeFromTargetAddress(info->target_address()));
if (target->is_inline_cache_stub()) {
ICUtility::Clear(this->GetIsolate(), info->pc(),
info->host()->constant_pool());
}
}
}
namespace {
template <typename Code>
void SetStackFrameCacheCommon(Handle<Code> code,
......@@ -14684,21 +14672,6 @@ void Code::Disassemble(const char* name, std::ostream& os) { // NOLINT
const char* n = CodeStub::MajorName(CodeStub::GetMajorKey(this));
os << "major_key = " << (n == NULL ? "null" : n) << "\n";
}
if (is_inline_cache_stub()) {
if (is_compare_ic_stub()) {
InlineCacheState ic_state = IC::StateFromCode(this);
os << "ic_state = " << ICState2String(ic_state) << "\n";
PrintExtraICState(os, kind(), extra_ic_state());
}
if (is_compare_ic_stub()) {
DCHECK(CodeStub::GetMajorKey(this) == CodeStub::CompareIC);
CompareICStub stub(stub_key(), GetIsolate());
os << "compare_state = " << CompareICState::GetStateName(stub.left())
<< "*" << CompareICState::GetStateName(stub.right()) << " -> "
<< CompareICState::GetStateName(stub.state()) << "\n";
os << "compare_operation = " << Token::Name(stub.op()) << "\n";
}
}
if ((name != nullptr) && (name[0] != '\0')) {
os << "name = " << name << "\n";
} else if (kind() == BYTECODE_HANDLER) {
......
......@@ -3663,8 +3663,7 @@ class Code: public HeapObject {
V(KEYED_LOAD_IC) \
V(STORE_IC) \
V(STORE_GLOBAL_IC) \
V(KEYED_STORE_IC) \
V(COMPARE_IC)
V(KEYED_STORE_IC)
#define CODE_KIND_LIST(V) \
NON_IC_KIND_LIST(V) \
......@@ -3753,13 +3752,11 @@ class Code: public HeapObject {
// [flags]: Access to specific code flags.
inline Kind kind() const;
inline ExtraICState extra_ic_state() const; // Only valid for IC stubs.
// Testers for IC stub kinds.
inline bool is_inline_cache_stub() const;
inline bool is_handler() const;
inline bool is_stub() const;
inline bool is_compare_ic_stub() const;
inline bool is_optimized_code() const;
inline bool is_wasm_code() const;
......@@ -3832,9 +3829,6 @@ class Code: public HeapObject {
inline bool back_edges_patched_for_osr() const;
// [to_boolean_foo]: For kind TO_BOOLEAN_IC tells what state the stub is in.
inline uint16_t to_boolean_state();
// [marked_for_deoptimization]: For kind OPTIMIZED_FUNCTION tells whether
// the code is going to be deoptimized because of dead embedded maps.
inline bool marked_for_deoptimization() const;
......@@ -4002,8 +3996,6 @@ class Code: public HeapObject {
DECL_PRINTER(Code)
DECL_VERIFIER(Code)
void ClearInlineCaches();
#define DECL_CODE_AGE_ENUM(X) k##X##CodeAge,
enum Age {
kToBeExecutedOnceCodeAge = -3,
......
This diff is collapsed.
......@@ -478,10 +478,6 @@ RUNTIME_FUNCTION(Runtime_ClearFunctionFeedback) {
DCHECK_EQ(1, args.length());
CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
function->ClearTypeFeedbackInfo();
Code* unoptimized = function->shared()->code();
if (unoptimized->kind() == Code::FUNCTION) {
unoptimized->ClearInlineCaches();
}
return isolate->heap()->undefined_value();
}
......
......@@ -658,7 +658,6 @@ namespace internal {
// Most intrinsics are implemented in the runtime/ directory, but ICs are
// implemented in ic.cc for now.
#define FOR_EACH_INTRINSIC_IC(F) \
F(CompareIC_Miss, 3, 1) \
F(ElementsTransitionAndStoreIC_Miss, 6, 1) \
F(KeyedLoadIC_Miss, 4, 1) \
F(KeyedStoreIC_Miss, 5, 1) \
......
This diff is collapsed.
......@@ -44,11 +44,6 @@ void StartupSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code,
} else if (obj->IsBytecodeArray()) {
obj = isolate()->heap()->undefined_value();
}
} else if (obj->IsCode()) {
Code* code = Code::cast(obj);
if (code->kind() == Code::FUNCTION) {
code->ClearInlineCaches();
}
}
if (SerializeHotObject(obj, how_to_code, where_to_point, skip)) return;
......
......@@ -1065,8 +1065,6 @@
'ic/handler-configuration-inl.h',
'ic/handler-configuration.h',
'ic/ic-inl.h',
'ic/ic-state.cc',
'ic/ic-state.h',
'ic/ic-stats.cc',
'ic/ic-stats.h',
'ic/ic.cc',
......@@ -1513,7 +1511,6 @@
'debug/arm/debug-arm.cc',
'ic/arm/access-compiler-arm.cc',
'ic/arm/handler-compiler-arm.cc',
'ic/arm/ic-arm.cc',
'regexp/arm/regexp-macro-assembler-arm.cc',
'regexp/arm/regexp-macro-assembler-arm.h',
],
......@@ -1561,7 +1558,6 @@
'debug/arm64/debug-arm64.cc',
'ic/arm64/access-compiler-arm64.cc',
'ic/arm64/handler-compiler-arm64.cc',
'ic/arm64/ic-arm64.cc',
'regexp/arm64/regexp-macro-assembler-arm64.cc',
'regexp/arm64/regexp-macro-assembler-arm64.h',
],
......@@ -1593,7 +1589,6 @@
'debug/ia32/debug-ia32.cc',
'ic/ia32/access-compiler-ia32.cc',
'ic/ia32/handler-compiler-ia32.cc',
'ic/ia32/ic-ia32.cc',
'regexp/ia32/regexp-macro-assembler-ia32.cc',
'regexp/ia32/regexp-macro-assembler-ia32.h',
],
......@@ -1626,7 +1621,6 @@
'debug/mips/debug-mips.cc',
'ic/mips/access-compiler-mips.cc',
'ic/mips/handler-compiler-mips.cc',
'ic/mips/ic-mips.cc',
'regexp/mips/regexp-macro-assembler-mips.cc',
'regexp/mips/regexp-macro-assembler-mips.h',
],
......@@ -1659,7 +1653,6 @@
'debug/mips64/debug-mips64.cc',
'ic/mips64/access-compiler-mips64.cc',
'ic/mips64/handler-compiler-mips64.cc',
'ic/mips64/ic-mips64.cc',
'regexp/mips64/regexp-macro-assembler-mips64.cc',
'regexp/mips64/regexp-macro-assembler-mips64.h',
],
......@@ -1694,7 +1687,6 @@
'debug/x64/debug-x64.cc',
'ic/x64/access-compiler-x64.cc',
'ic/x64/handler-compiler-x64.cc',
'ic/x64/ic-x64.cc',
'regexp/x64/regexp-macro-assembler-x64.cc',
'regexp/x64/regexp-macro-assembler-x64.h',
'third_party/valgrind/valgrind.h',
......@@ -1712,7 +1704,6 @@
'debug/ppc/debug-ppc.cc',
'ic/ppc/access-compiler-ppc.cc',
'ic/ppc/handler-compiler-ppc.cc',
'ic/ppc/ic-ppc.cc',
'ppc/assembler-ppc-inl.h',
'ppc/assembler-ppc.cc',
'ppc/assembler-ppc.h',
......@@ -1745,7 +1736,6 @@
'debug/s390/debug-s390.cc',
'ic/s390/access-compiler-s390.cc',
'ic/s390/handler-compiler-s390.cc',
'ic/s390/ic-s390.cc',
'regexp/s390/regexp-macro-assembler-s390.cc',
'regexp/s390/regexp-macro-assembler-s390.h',
's390/assembler-s390.cc',
......
This diff is collapsed.
......@@ -3143,19 +3143,6 @@ TEST(IncrementalMarkingPreservesMonomorphicCallIC) {
}
static Code* FindFirstIC(Code* code, Code::Kind kind) {
int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET);
for (RelocIterator it(code, mask); !it.done(); it.next()) {
RelocInfo* info = it.rinfo();
Code* target = Code::GetCodeFromTargetAddress(info->target_address());
if (target->is_inline_cache_stub() && target->kind() == kind) {
return target;
}
}
return NULL;
}
static void CheckVectorIC(Handle<JSFunction> f, int slot_index,
InlineCacheState desired_state) {
Handle<FeedbackVector> vector = Handle<FeedbackVector>(f->feedback_vector());
......@@ -4512,20 +4499,15 @@ Handle<JSFunction> GetFunctionByName(Isolate* isolate, const char* name) {
void CheckIC(Handle<JSFunction> function, Code::Kind kind, int slot_index,
InlineCacheState state) {
if (kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC) {
FeedbackVector* vector = function->feedback_vector();
FeedbackSlot slot(slot_index);
if (kind == Code::LOAD_IC) {
LoadICNexus nexus(vector, slot);
CHECK_EQ(nexus.StateFromFeedback(), state);
} else if (kind == Code::KEYED_LOAD_IC) {
KeyedLoadICNexus nexus(vector, slot);
CHECK_EQ(nexus.StateFromFeedback(), state);
}
} else {
Code* ic = FindFirstIC(function->code(), kind);
CHECK(ic->is_inline_cache_stub());
CHECK_EQ(state, IC::StateFromCode(ic));
CHECK(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC);
FeedbackVector* vector = function->feedback_vector();
FeedbackSlot slot(slot_index);
if (kind == Code::LOAD_IC) {
LoadICNexus nexus(vector, slot);
CHECK_EQ(nexus.StateFromFeedback(), state);
} else if (kind == Code::KEYED_LOAD_IC) {
KeyedLoadICNexus nexus(vector, slot);
CHECK_EQ(nexus.StateFromFeedback(), state);
}
}
......
......@@ -85,17 +85,6 @@ code is governed by a BSD-style license that can be found in the LICENSE file.
old_state, new_state, map, slow_reason));
}
processCompareIC(pc, line, column, stub, op, old_left, old_right,
old_state, new_left, new_right, new_state) {
let fnName = this.functionName(pc);
this.entries.push(new Entry("CompareIC", fnName, line, column, name,
old_state, new_state));
}
processPatchIC(pc, test, delta) {
}
};
......
......@@ -56,13 +56,6 @@ function IcProcessor() {
'KeyedStoreIC': {
parsers : propertyICParser,
processor: this.processPropertyIC.bind(this, "KeyedStoreIC") },
'CompareIC': {
parsers : [parseInt, parseInt, parseInt, parseInt, null, null, null,
null, null, null, null],
processor: this.processCompareIC },
'PatchIC': {
parsers : [parseInt, parseInt, parseInt],
processor: this.processPatchIC },
});
this.deserializedEntriesNames_ = [];
this.profile_ = new Profile();
......@@ -71,8 +64,6 @@ function IcProcessor() {
this.StoreIC = 0;
this.KeyedLoadIC = 0;
this.KeyedStoreIC = 0;
this.CompareIC = 0;
this.PatchIC = 0;
}
inherits(IcProcessor, LogReader);
......@@ -113,8 +104,6 @@ IcProcessor.prototype.processLogFile = function(fileName) {
print("Store: " + this.StoreIC);
print("KeyedLoad: " + this.KeyedLoadIC);
print("KeyedStore: " + this.KeyedStoreIC);
print("CompareIC: " + this.CompareIC);
print("PatchIC: " + this.PatchIC);
};
IcProcessor.prototype.addEntry = function(entry) {
......@@ -170,24 +159,6 @@ IcProcessor.prototype.processPropertyIC = function (
" (map 0x" + map.toString(16) + ")");
}
IcProcessor.prototype.processCompareIC = function (
pc, line, column, stub, op, old_left, old_right, old_state, new_left,
new_right, new_state) {
var entry = this.profile_.findEntry(pc);
this.CompareIC++;
print("CompareIC[" + op + "] ((" +
old_left + "+" + old_right + "=" + old_state + ")->(" +
new_left + "+" + new_right + "=" + new_state + ")) at " +
this.formatName(entry) + ":" + line + ":" + column);
}
IcProcessor.prototype.processPatchIC = function (pc, test, delta) {
var entry = this.profile_.findEntry(pc);
this.PatchIC++;
print("PatchIC (0x" + test.toString(16) + ", " + delta + ") at " +
this.formatName(entry));
}
function padLeft(s, len) {
s = s.toString();
if (s.length < len) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment