beb7114861
This relands commit b0a71d364c
Cq-Include-Trybots: dart/try:vm-kernel-precomp-linux-release-simarm64-try,vm-kernel-precomp-linux-release-simarm-try,vm-kernel-linux-release-simarm64-try,vm-kernel-linux-release-simarm-try,vm-kernel-precomp-linux-release-x64-try
Change-Id: I1d32e5d0d44f4e422d188643b548ed81859f7d74
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/143807
Commit-Queue: Vyacheslav Egorov <vegorov@google.com>
Reviewed-by: Vyacheslav Egorov <vegorov@google.com>
208 lines
7.0 KiB
C++
208 lines
7.0 KiB
C++
// 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"
|
|
|
|
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());
|
|
const intptr_t kHashBits = 30;
|
|
uint32_t fp = 0;
|
|
fp = CombineHashes(fp, String::Handle(function.UserVisibleName()).Hash());
|
|
if (function.is_abstract()) {
|
|
return FinalizeHash(fp, kHashBits);
|
|
}
|
|
if (!function.HasBytecode()) {
|
|
kernel::BytecodeReader::ReadFunctionBytecode(Thread::Current(), function);
|
|
}
|
|
const Bytecode& code = Bytecode::Handle(function.bytecode());
|
|
const ObjectPool& pool = ObjectPool::Handle(code.object_pool());
|
|
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, kHashBits);
|
|
}
|
|
|
|
} // namespace kernel
|
|
} // namespace dart
|