track total size of static array and Unit/Class/Func
[hiphop-php.git] / hphp / runtime / base / record-common.cpp
blobbbf0f6ec27cac4ea47729fe9457258c2d17e04ce
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/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"
23 namespace HPHP {
24 RecordBase::RecordBase(const RecordDesc* record)
25 : m_record(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);
41 template
42 RecordData* RecordBase::copyRecordBase<RecordData>(const RecordData*,
43 AllocMode);
44 template
45 RecordArray* RecordBase::copyRecordBase<RecordArray>(const RecordArray*,
46 AllocMode);
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]);
57 return newRec;
60 template
61 RecordData* RecordBase::newRecordImpl<RecordData>(const RecordDesc* rec,
62 uint32_t initSize,
63 const StringData* const *keys,
64 const TypedValue* values);
65 template
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,
72 uint32_t initSize,
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);
79 auto const recdata =
80 new (NotNull{}, tl_heap->objMalloc(size)) RecordType(rec);
81 assertx(recdata->hasExactlyOneRef());
82 try {
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);
96 tvCopy(val, tv);
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) {
104 tvDup(val, tv);
105 } else {
106 raise_record_init_error(rec->name(), field.name());
109 } catch (...) {
110 recdata->decRefAndRelease();
111 throw;
113 return recdata;
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]));
126 } // namespace HPHP