Basic JIT support for Records
[hiphop-php.git] / hphp / runtime / vm / hhbc-codec.cpp
blob1f790dd1b95561b9486c446806c992bef4aa2cf0
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-present Facebook, Inc. (http://www.facebook.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
17 #include "hphp/runtime/vm/hhbc-codec.h"
18 #include "hphp/runtime/vm/unit-emitter.h"
19 #include "hphp/runtime/vm/unit.h"
21 namespace HPHP {
23 MemberKey decode_member_key(PC& pc, Either<const Unit*, const UnitEmitter*> u) {
24 auto const mcode = static_cast<MemberCode>(decode_byte(pc));
26 switch (mcode) {
27 case MEC: case MEL: case MPC: case MPL:
28 return MemberKey{mcode, decode_iva(pc)};
30 case MEI:
31 return MemberKey{mcode, decode_raw<int64_t>(pc)};
33 case MET: case MPT: case MQT: {
34 auto const id = decode_raw<Id>(pc);
35 auto const str = u.match(
36 [id](const Unit* u) { return u->lookupLitstrId(id); },
37 [id](const UnitEmitter* ue) { return ue->lookupLitstr(id); }
39 return MemberKey{mcode, str};
42 case MW:
43 return MemberKey{};
45 not_reached();
48 void encode_member_key(MemberKey mk, UnitEmitter& ue) {
49 ue.emitByte(mk.mcode);
51 switch (mk.mcode) {
52 case MEC: case MEL: case MPC: case MPL:
53 ue.emitIVA(mk.iva);
54 break;
56 case MEI:
57 ue.emitInt64(mk.int64);
58 break;
60 case MET: case MPT: case MQT:
61 ue.emitInt32(ue.mergeLitstr(mk.litstr));
62 break;
64 case MW:
65 // No immediate
66 break;
70 ///////////////////////////////////////////////////////////////////////////////
72 void encodeLocalRange(UnitEmitter& ue, const LocalRange& range) {
73 ue.emitIVA(range.first);
74 ue.emitIVA(range.count);
77 LocalRange decodeLocalRange(const unsigned char*& pc) {
78 auto const first = decode_iva(pc);
79 auto const restCount = decode_iva(pc);
80 return LocalRange{uint32_t(first), uint32_t(restCount)};
83 ///////////////////////////////////////////////////////////////////////////////
85 void encodeFCallArgsBase(UnitEmitter& ue, const FCallArgsBase& fca,
86 const uint8_t* byRefs, bool hasAsyncEagerOffset) {
87 auto constexpr kFirstNumArgsBit = FCallArgsBase::kFirstNumArgsBit;
88 bool smallNumArgs = ((fca.numArgs + 1) << kFirstNumArgsBit) <= 0xff;
89 auto flags = uint8_t{fca.flags};
90 assertx(!(flags & ~FCallArgsBase::kInternalFlags));
91 if (smallNumArgs) flags |= (fca.numArgs + 1) << kFirstNumArgsBit;
92 if (fca.numRets != 1) flags |= FCallArgsBase::HasInOut;
93 if (byRefs != nullptr) flags |= FCallArgsBase::EnforceReffiness;
94 if (hasAsyncEagerOffset) flags |= FCallArgsBase::HasAsyncEagerOffset;
96 ue.emitByte(flags);
97 if (!smallNumArgs) ue.emitIVA(fca.numArgs);
98 if (fca.numRets != 1) ue.emitIVA(fca.numRets);
100 if (byRefs != nullptr) {
101 auto const numBytes = (fca.numArgs + 7) / 8;
102 for (auto i = 0; i < numBytes; ++i) ue.emitByte(byRefs[i]);
106 FCallArgs decodeFCallArgs(PC& pc) {
107 auto const flags = decode_byte(pc);
108 auto const numArgs = (flags >> FCallArgs::kFirstNumArgsBit)
109 ? (flags >> FCallArgs::kFirstNumArgsBit) - 1 : decode_iva(pc);
110 auto const numRets = (flags & FCallArgs::HasInOut) ? decode_iva(pc) : 1;
111 auto const byRefs = (flags & FCallArgs::EnforceReffiness) ? pc : nullptr;
112 if (byRefs != nullptr) pc += (numArgs + 7) / 8;
113 auto const asyncEagerOffset = (flags & FCallArgs::HasAsyncEagerOffset)
114 ? decode_ba(pc) : kInvalidOffset;
115 return FCallArgs(
116 static_cast<FCallArgs::Flags>(flags & FCallArgs::kInternalFlags),
117 numArgs, numRets, byRefs, asyncEagerOffset
121 ///////////////////////////////////////////////////////////////////////////////