blob: aa3e4b764b1ea48874cc14bf17a8d53ed752bf77 [file] [log] [blame]
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "vm/compiler/frontend/bytecode_fingerprints.h"
#include "vm/compiler/frontend/bytecode_reader.h"
#include "vm/constants_kbc.h"
#include "vm/hash.h"
#if !defined(DART_PRECOMPILED_RUNTIME)
namespace dart {
namespace kernel {
static uint32_t CombineObject(uint32_t hash, const Object& obj) {
if (obj.IsAbstractType()) {
return CombineHashes(hash, AbstractType::Cast(obj).Hash());
} else if (obj.IsClass()) {
return CombineHashes(hash, Class::Cast(obj).id());
} else if (obj.IsFunction()) {
return CombineHashes(
hash, AbstractType::Handle(Function::Cast(obj).result_type()).Hash());
} else if (obj.IsField()) {
return CombineHashes(hash,
AbstractType::Handle(Field::Cast(obj).type()).Hash());
} else {
return CombineHashes(hash, static_cast<uint32_t>(obj.GetClassId()));
}
}
typedef uint32_t (*Fp)(uint32_t fp,
const KBCInstr* instr,
const ObjectPool& pool,
int32_t value);
static uint32_t Fp___(uint32_t fp,
const KBCInstr* instr,
const ObjectPool& pool,
int32_t value) {
return fp;
}
static uint32_t Fptgt(uint32_t fp,
const KBCInstr* instr,
const ObjectPool& pool,
int32_t value) {
return CombineHashes(fp, value);
}
static uint32_t Fplit(uint32_t fp,
const KBCInstr* instr,
const ObjectPool& pool,
int32_t value) {
return CombineObject(fp, Object::Handle(pool.ObjectAt(value)));
}
static uint32_t Fpreg(uint32_t fp,
const KBCInstr* instr,
const ObjectPool& pool,
int32_t value) {
return CombineHashes(fp, value);
}
static uint32_t Fpxeg(uint32_t fp,
const KBCInstr* instr,
const ObjectPool& pool,
int32_t value) {
return CombineHashes(fp, value);
}
static uint32_t Fpnum(uint32_t fp,
const KBCInstr* instr,
const ObjectPool& pool,
int32_t value) {
return CombineHashes(fp, value);
}
static uint32_t Fingerprint0(uint32_t fp,
const KBCInstr* instr,
const ObjectPool& pool,
Fp op1,
Fp op2,
Fp op3) {
return fp;
}
static uint32_t FingerprintA(uint32_t fp,
const KBCInstr* instr,
const ObjectPool& pool,
Fp op1,
Fp op2,
Fp op3) {
fp = op1(fp, instr, pool, KernelBytecode::DecodeA(instr));
return fp;
}
static uint32_t FingerprintD(uint32_t fp,
const KBCInstr* instr,
const ObjectPool& pool,
Fp op1,
Fp op2,
Fp op3) {
fp = op1(fp, instr, pool, KernelBytecode::DecodeD(instr));
return fp;
}
static uint32_t FingerprintX(uint32_t fp,
const KBCInstr* instr,
const ObjectPool& pool,
Fp op1,
Fp op2,
Fp op3) {
fp = op1(fp, instr, pool, KernelBytecode::DecodeX(instr));
return fp;
}
static uint32_t FingerprintT(uint32_t fp,
const KBCInstr* instr,
const ObjectPool& pool,
Fp op1,
Fp op2,
Fp op3) {
fp = op1(fp, instr, pool, KernelBytecode::DecodeT(instr));
return fp;
}
static uint32_t FingerprintA_E(uint32_t fp,
const KBCInstr* instr,
const ObjectPool& pool,
Fp op1,
Fp op2,
Fp op3) {
fp = op1(fp, instr, pool, KernelBytecode::DecodeA(instr));
fp = op2(fp, instr, pool, KernelBytecode::DecodeE(instr));
return fp;
}
static uint32_t FingerprintA_Y(uint32_t fp,
const KBCInstr* instr,
const ObjectPool& pool,
Fp op1,
Fp op2,
Fp op3) {
fp = op1(fp, instr, pool, KernelBytecode::DecodeA(instr));
fp = op2(fp, instr, pool, KernelBytecode::DecodeY(instr));
return fp;
}
static uint32_t FingerprintD_F(uint32_t fp,
const KBCInstr* instr,
const ObjectPool& pool,
Fp op1,
Fp op2,
Fp op3) {
fp = op1(fp, instr, pool, KernelBytecode::DecodeD(instr));
fp = op2(fp, instr, pool, KernelBytecode::DecodeF(instr));
return fp;
}
static uint32_t FingerprintA_B_C(uint32_t fp,
const KBCInstr* instr,
const ObjectPool& pool,
Fp op1,
Fp op2,
Fp op3) {
fp = op1(fp, instr, pool, KernelBytecode::DecodeA(instr));
fp = op2(fp, instr, pool, KernelBytecode::DecodeB(instr));
fp = op3(fp, instr, pool, KernelBytecode::DecodeC(instr));
return fp;
}
uint32_t BytecodeFingerprintHelper::CalculateFunctionFingerprint(
const Function& function) {
ASSERT(function.is_declared_in_bytecode());
if (function.is_abstract()) {
return 0;
}
if (!function.HasBytecode()) {
kernel::BytecodeReader::ReadFunctionBytecode(Thread::Current(), function);
}
const Bytecode& code = Bytecode::Handle(function.bytecode());
const ObjectPool& pool = ObjectPool::Handle(code.object_pool());
uint32_t fp = 0;
const KBCInstr* const start =
reinterpret_cast<const KBCInstr*>(code.instructions());
for (const KBCInstr* instr = start; (instr - start) < code.Size();
instr = KernelBytecode::Next(instr)) {
const KernelBytecode::Opcode opcode = KernelBytecode::DecodeOpcode(instr);
fp = CombineHashes(fp, opcode);
switch (opcode) {
#define FINGERPRINT_BYTECODE(name, encoding, kind, op1, op2, op3) \
case KernelBytecode::k##name: \
fp = Fingerprint##encoding(fp, instr, pool, Fp##op1, Fp##op2, Fp##op3); \
break;
KERNEL_BYTECODES_LIST(FINGERPRINT_BYTECODE)
#undef FINGERPRINT_BYTECODE
default:
UNREACHABLE();
}
}
return FinalizeHash(fp, 30);
}
} // namespace kernel
} // namespace dart
#endif // !defined(DART_PRECOMPILED_RUNTIME)