2 +----------------------------------------------------------------------+
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/base/record-array.h"
18 #include "hphp/runtime/base/record-common.h"
19 #include "hphp/runtime/base/record-data.h"
20 #include "hphp/runtime/base/runtime-error.h"
21 #include "hphp/runtime/base/tv-mutate.h"
24 RecordBase::RecordBase(const RecordDesc
* record
)
26 static_assert(KindOfUninit
== static_cast<DataType
>(0),
27 "RecordBase assumes KindOfUninit == 0");
28 memset(const_cast<TypedValue
*>(fieldVec()), 0, fieldSize(record
));
31 template<class RecordType
>
32 RecordType
* RecordBase::allocRecord(size_t size
, AllocMode mode
) {
33 if (mode
== AllocMode::Request
) {
34 return static_cast<RecordType
*>(tl_heap
->objMalloc(size
));
36 auto const mem
= RuntimeOption::EvalLowStaticArrays
?
37 lower_malloc(size
) : uncounted_malloc(size
);
38 return static_cast<RecordType
*>(mem
);
42 RecordData
* RecordBase::copyRecordBase
<RecordData
>(const RecordData
*,
45 RecordArray
* RecordBase::copyRecordBase
<RecordArray
>(const RecordArray
*,
48 template<class RecordType
>
49 RecordType
* RecordBase::copyRecordBase(const RecordType
* old
, AllocMode mode
) {
50 auto const size
= RecordType::sizeWithFields(old
->record());
51 auto const newRec
= allocRecord
<RecordType
>(size
, mode
);
52 memcpy(newRec
, old
, size
);
53 auto const fields
= newRec
->fieldVec();
54 for (auto i
= 0; i
< old
->record()->numFields(); ++i
) {
55 tvIncRefGen(fields
[i
]);
61 RecordData
* RecordBase::newRecordImpl
<RecordData
>(const RecordDesc
* rec
,
63 const StringData
* const *keys
,
64 const TypedValue
* values
);
66 RecordArray
* RecordBase::newRecordImpl
<RecordArray
>(
67 const RecordDesc
* rec
, uint32_t initSize
, const StringData
* const *keys
,
68 const TypedValue
* values
);
70 template<class RecordType
>
71 RecordType
* RecordBase::newRecordImpl(const RecordDesc
* rec
,
73 const StringData
* const *keys
,
74 const TypedValue
* values
) {
75 if (rec
->attrs() & AttrAbstract
) {
76 raise_error("Cannot instantiate abstract record %s", rec
->name()->data());
78 auto const size
= RecordType::sizeWithFields(rec
);
80 new (NotNull
{}, tl_heap
->objMalloc(size
)) RecordType(rec
);
81 assertx(recdata
->hasExactlyOneRef());
83 for (auto i
= 0; i
< initSize
; ++i
) {
84 auto const name
= keys
[i
];
85 auto const idx
= rec
->lookupField(name
);
86 if (idx
== kInvalidSlot
) {
87 raise_record_field_error(rec
->name(), name
);
89 const auto& field
= rec
->field(idx
);
90 auto const& val
= values
[initSize
- i
-1];
91 auto const& tc
= field
.typeConstraint();
92 if (tc
.isCheckable()) {
93 tc
.verifyRecField(&val
, rec
->name(), field
.name());
95 auto const& tv
= recdata
->lvalAt(idx
);
98 for (auto i
= 0; i
< rec
->numFields(); ++i
) {
99 auto const field
= rec
->field(i
);
100 auto const& tv
= recdata
->lvalAt(i
);
101 if (type(tv
) != KindOfUninit
) continue;
102 auto const& val
= field
.val();
103 if (val
.m_type
!= KindOfUninit
) {
106 raise_record_init_error(rec
->name(), field
.name());
110 recdata
->decRefAndRelease();
116 tv_rval
RecordBase::rvalAt(Slot idx
) const {
117 assertx(idx
!= kInvalidSlot
&& idx
< record()->numFields());
118 return tv_rval(&fieldVec()[idx
]);
121 tv_lval
RecordBase::lvalAt(Slot idx
) {
122 assertx(idx
!= kInvalidSlot
&& idx
< record()->numFields());
123 return tv_lval(const_cast<TypedValue
*>(&fieldVec()[idx
]));